/*
 * @(#)OctS.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 Oct */

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

#define MAX_CORNERS 6

static int edgeMateFace[MAX_FACES][3] =
{
	{1, 3, 6}, {2, 0, 5}, {3, 1, 4}, {0, 2, 7},
	{5, 7, 2}, {6, 4, 1}, {7, 5, 0}, {4, 6, 3}
};

static int edgeMateCorner[MAX_FACES][3] =
{
	{3, 1, 6}, {0, 2, 5}, {1, 3, 4}, {2, 0, 7},
	{7, 5, 2}, {4, 6, 1}, {5, 7, 0}, {6, 4, 3}
};

static int facesAtCorner[MAX_CORNERS][4] =
{
	{0, 1, 2, 3},
	{0, 6, 5, 1}, {1, 5, 4, 2}, {2, 4, 7, 3}, {3, 7, 6, 0},
	{6, 7, 4, 5}
};
static int orientAtCorner[MAX_CORNERS][4] =
{
	{0, 0, 0, 0},
	{1, 2, 1, 2}, {1, 2, 1, 2}, {1, 2, 1, 2}, {1, 2, 1, 2},
	{0, 0, 0, 0}
};
static int facesToCorner[MAX_FACES][3] =
{
	{0, 1, 4}, {0, 2, 1}, {0, 3, 2}, {0, 4, 3},
	{5, 2, 3}, {5, 1, 2}, {5, 4, 1}, {5, 3, 4}
};
static int faceCornerToOther[MAX_FACES][3][3] =
{
	{{1, 2, 3}, {6, 5, 1}, {3, 7, 6}},
	{{2, 3, 0}, {5, 4, 2}, {0, 6, 5}},
	{{3, 0, 1}, {4, 7, 3}, {1, 5, 4}},
	{{0, 1, 2}, {7, 6, 0}, {2, 4, 7}},
	{{5, 6, 7}, {2, 1, 5}, {7, 3, 2}},
	{{6, 7, 4}, {1, 0, 6}, {4, 2, 1}},
	{{7, 4, 5}, {0, 3, 7}, {5, 1, 0}},
	{{4, 5, 6}, {3, 2, 4}, {6, 0, 3}}
};
static int orientCornerToOther[3][3] =
{
	{0, 0, 0}, {2, 1, 2}, {1, 2, 1}
};

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(OctWidget 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(OctWidget w)
{
	XEvent event;

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

static void
movePuzzlePiece(OctWidget w, int face, int position,
	int direction, int style, 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
	movePuzzleDelay(w, face, position, direction, style, control);
}

static int
indexToCorner(OctWidget w, int cornerIndex) {
	switch (cornerIndex) { /* Oct -> 0, 4, 8 */
	case 0:
		return 0;
	case 1:
		return (w->oct.size - 1) * (w->oct.size - 1);
	case 2:
		return w->oct.size * w->oct.size - 1;
	default:
		(void) printf("corner unknown %d\n", cornerIndex);
	}
	return -1;
}

static int
indexToCornerMate(OctWidget w, int cornerIndex) {
	switch (cornerIndex) { /* Oct -> 0, 8, 4 */
	case 0:
		return 0;
	case 1:
		return w->oct.size * w->oct.size - 1;
	case 2:
		return (w->oct.size - 1) * (w->oct.size - 1);
	default:
		(void) printf("corner unknown %d\n", cornerIndex);
	}
	return -1;
}

static int
cornerToIndex(OctWidget w, int corner) {
	int temp; /* Oct -> {0, -1, -1, -1, 1, -1, -1, -1, 2} */

	if (corner == 0)
		return 0;
	temp = (w->oct.size - 1) * (w->oct.size - 1) - corner;
	if (temp == 0)
		return 1;
	else if (temp < 0) {
		temp = w->oct.size * w->oct.size - 1 - corner;
		if (temp == 0)
			return 2;
	}
	return -1;
}

static int
indexToEdge(OctWidget w, int edgeIndex) {
	switch (edgeIndex) { /* Oct -> 1, 3, 6 */
	case 0:
		return (w->oct.size >> 1) * (w->oct.size >> 1)
			+ (((w->oct.size & 1) == 0) ? 1 : 0);
	case 1:
		return (w->oct.size >> 1) * (w->oct.size >> 1)
			+ 2 * (w->oct.size >> 1)
			- (((w->oct.size & 1) == 0) ? 1 : 0);
	case 2:
		return w->oct.size * w->oct.size - w->oct.size;
	default:
		(void) printf("edge unknown %d\n", edgeIndex);
	}
	return -1;
}

static int
indexToEdgeMate(OctWidget w, int edgeIndex) {
	switch (edgeIndex) { /* Oct -> 3, 1, 6 */
	case 0:
		return (w->oct.size >> 1) * (w->oct.size >> 1)
			+ 2 * (w->oct.size >> 1)
			- (((w->oct.size & 1) == 0) ? 1 : 0);
	case 1:
		return (w->oct.size >> 1) * (w->oct.size >> 1)
			+ (((w->oct.size & 1) == 0) ? 1 : 0);
	case 2:
		return w->oct.size * w->oct.size - w->oct.size;
	default:
		(void) printf("edge unknown %d\n", edgeIndex);
	}
	return -1;
}

static int
edgeToIndex(OctWidget w, int edge) {
	int temp; /* Oct -> {-1, 0, -1, 1, -1, -1, 2, -1, -1} */

	temp = (w->oct.size >> 1) * (w->oct.size >> 1)
		+ 2 * (w->oct.size >> 1)
		- (((w->oct.size & 1) == 0) ? 1 : 0)
		- edge;
	if (temp == 0) {
		return 1;
	} else if (temp > 0) {
		temp = (w->oct.size >> 1) * (w->oct.size >> 1)
			+ (((w->oct.size & 1) == 0) ? 1 : 0)
			- edge;
		if (temp == 0) {
			return 0;
		}
	} else if (temp < 0) {
		temp = w->oct.size * w->oct.size - w->oct.size
			- edge;
		if (temp == 0) {
			return 2;
		}
	}
	return -1;
}

static int
indexToCenter(OctWidget w, int centerIndex) {
	switch (centerIndex) { /* Oct -> 2, 5, 7 */
	case 0:
		return 2;
	case 1:
		return (w->oct.size - 1) * (w->oct.size - 1) + 1;
	case 2:
		return w->oct.size * w->oct.size - 2;
	default:
		(void) printf("center unknown %d\n", centerIndex);
	}
	return -1;
}

#if 0
static int
centerToIndex(OctWidget w, int center) {
	int temp; /* Oct-> {-1, -1, 0, -1, -1, 1, -1, 2, -1} */

	if (center == 2)
		return 0;
	temp = (w->oct.size - 1) * (w->oct.size - 1) + 1 - center;
	if (temp == 0)
		return 2;
	else if (temp < 0) {
		temp = w->oct.size * w->oct.size - 2 - center;
		if (temp == 0)
			return 1;
	}
	return -1;
}
#endif

static void
rotateCornerEdgeCW(OctWidget w, int corner)
{
	int face = facesAtCorner[corner][3];
	int position = indexToEdge(w, orientAtCorner[corner][3]);

	if (corner == 0 || corner == 5)
		movePuzzlePiece(w, face, position, CW, PERIOD4, FALSE);
	else
		movePuzzlePiece(w, face, position,
			((TL / 2 + corner - 1) % 4 * 2 + TR), PERIOD4, FALSE);
}

static void
rotateCornerEdgeCCW(OctWidget w, int corner)
{
	int face = facesAtCorner[corner][0];
	int position = indexToEdgeMate(w, orientAtCorner[corner][0]);

	if (corner == 0 || corner == 5)
		movePuzzlePiece(w, face, position, CCW, PERIOD4, FALSE);
	else
		movePuzzlePiece(w, face, position,
			((BR / 2 + corner - 1) % 4 * 2 + TR), PERIOD4, FALSE);
}

static void
rotateCornerEdgeHalf(OctWidget w, int corner)
{
	if (NRAND(2) == 0) {
		rotateCornerEdgeCW(w, corner);
		rotateCornerEdgeCW(w, corner);
	} else {
		rotateCornerEdgeCCW(w, corner);
		rotateCornerEdgeCCW(w, corner);
	}
}

static void
rotateCornerCenterCW(OctWidget w, int corner)
{
	int face = facesAtCorner[corner][3];
	int position = indexToCenter(w, orientAtCorner[corner][3]);

	if (corner == 0 || corner == 5)
		movePuzzlePiece(w, face, position, CW, PERIOD4, FALSE);
	else
		movePuzzlePiece(w, face, position,
			((TL / 2 + corner - 1) % 4 * 2 + TR), PERIOD4, FALSE);
}

static void
rotateCornerCenterCCW(OctWidget w, int corner)
{
	int face = facesAtCorner[corner][0];
	int position = indexToCenter(w, orientAtCorner[corner][0]);

	if (corner == 0 || corner == 5)
		movePuzzlePiece(w, face, position, CCW, PERIOD4, FALSE);
	else
		movePuzzlePiece(w, face, position,
			((BR / 2 + corner - 1) % 4 * 2 + TR), PERIOD4, FALSE);
}

static void
rotateCornerCenterHalf(OctWidget w, int corner)
{
	if (NRAND(2) == 0) {
		rotateCornerCenterCW(w, corner);
		rotateCornerCenterCW(w, corner);
	} else {
		rotateCornerCenterCCW(w, corner);
		rotateCornerCenterCCW(w, corner);
	}
}

static void
rotatePuzzleCW(OctWidget w, int corner)
{
	int face = facesAtCorner[corner][3];
	int position = indexToEdge(w, orientAtCorner[corner][3]);

	if (corner == 0 || corner == 5)
		movePuzzlePiece(w, face, position, CW, PERIOD4, TRUE);
	else
		movePuzzlePiece(w, face, position,
			((TL / 2 + corner - 1) % 4 * 2 + TR), PERIOD4, TRUE);
}

static void
rotatePuzzleCCW(OctWidget w, int corner)
{
	int face = facesAtCorner[corner][0];
	int position = indexToEdge(w, orientAtCorner[corner][0]);

	if (corner == 0 || corner == 5)
		movePuzzlePiece(w, face, position, CCW, PERIOD4, TRUE);
	else
		movePuzzlePiece(w, face, position,
			((BR / 2 + corner - 1) % 4 * 2 + TR), PERIOD4, TRUE);
}

static void
rotatePuzzleHalf(OctWidget w, int corner)
{
	if (NRAND(2) == 0) {
		rotatePuzzleCW(w, corner);
		rotatePuzzleCW(w, corner);
	} else {
		rotatePuzzleCCW(w, corner);
		rotatePuzzleCCW(w, corner);
	}
}

static void
rotateTrivialCornerCW(OctWidget w, int corner)
{
	int face = facesAtCorner[corner][3];
	int position = indexToCorner(w, orientAtCorner[corner][3]);

	if (corner == 0 || corner == 5)
		movePuzzlePiece(w, face, position, CW, PERIOD4, FALSE);
	else
		movePuzzlePiece(w, face, position,
			((TL / 2 + corner - 1) % 4 * 2 + TR), PERIOD4, FALSE);
}

static void
rotateTrivialCornerCCW(OctWidget w, int corner)
{
	int face = facesAtCorner[corner][0];
	int position = indexToCorner(w, orientAtCorner[corner][0]);

	if (corner == 0 || corner == 5)
		movePuzzlePiece(w, face, position, CCW, PERIOD4, FALSE);
	else
		movePuzzlePiece(w, face, position,
			((BR / 2 + corner - 1) % 4 * 2 + TR), PERIOD4, FALSE);
}

static void
rotateTrivialCornerHalf(OctWidget w, int corner)
{
	if (NRAND(2) == 0) {
		rotateTrivialCornerCW(w, corner);
		rotateTrivialCornerCW(w, corner);
	} else {
		rotateTrivialCornerCCW(w, corner);
		rotateTrivialCornerCCW(w, corner);
	}
}

/* This is impossible to do with Drag and Drop as implemented.
 * Use the keypad.  Turn the trivial corners so that the
 * colors match the adjacent pieces all around. */
static void
orientTrivialCorners(OctWidget w, int corner)
{
	int face = facesAtCorner[corner][0];
	int orient = orientAtCorner[corner][0];
	int cornerPosition = indexToCorner(w, orient);
	int centerPosition = indexToCenter(w, orient);
	int cornerColor = w->oct.facetLoc[face][cornerPosition].face;
	int centerColor = w->oct.facetLoc[face][centerPosition].face;

	if (cornerColor == centerColor) {
		return;
	}
	face = facesAtCorner[corner][1];
	orient = orientAtCorner[corner][1];
	centerPosition = indexToCenter(w, orient);
	centerColor = w->oct.facetLoc[face][centerPosition].face;
	if (cornerColor == centerColor) {
		rotateTrivialCornerCW(w, corner);
		return;
	}
	face = facesAtCorner[corner][2];
	orient = orientAtCorner[corner][2];
	centerPosition = indexToCenter(w, orient);
	centerColor = w->oct.facetLoc[face][centerPosition].face;
	if (cornerColor == centerColor) {
		rotateTrivialCornerHalf(w, corner);
		return;
	}
	face = facesAtCorner[corner][3];
	orient = orientAtCorner[corner][3];
	centerPosition = indexToCenter(w, orient);
	centerColor = w->oct.facetLoc[face][centerPosition].face;
	if (cornerColor == centerColor) {
		rotateTrivialCornerCCW(w, corner);
		return;
	}
	(void) printf("no match %d, cornerColor %d, centerColor %d\n",
		corner, cornerColor, centerColor);
}

static int
findFaceColor(OctWidget w, int face)
{
	int colors[8];
	int point, color;

	for (color = 0; color < MAX_FACES; color++)
		colors[color] = 0;
	for (point = 0; point < 3; point++) {
		int side;
		int corner = facesToCorner[face][point];

		for (side = 0; side < 4; side++) {
			int otherFace = facesAtCorner[corner][side];
			int position = indexToCenter(w,
				orientAtCorner[corner][side]);

			color = w->oct.facetLoc[otherFace][position].face;
			colors[color]++;
			if (colors[color] == 3) {
#ifdef DEBUG
				(void) printf("Color for face %d is %d\n",
					face, color);
#endif
				return color;
			}
		}
	}
	(void) printf("No color found for %d\n", face);
	return MAX_FACES;
}

static void
faceCorner(OctWidget w, int face, int faceColor, int point)
{
	int side;
	int corner = facesToCorner[face][point];
	int otherFace = face;
	int otherOrient = point;

	for (side = 0; side < 4; side++) {
		int position = indexToCenter(w, otherOrient);

		if (faceColor == w->oct.facetLoc[otherFace][position].face) {
			switch (side) {
			case 1:
				rotateCornerCenterCCW(w, corner);
				break;
			case 2:
				rotateCornerCenterHalf(w, corner);
				break;
			case 3:
				rotateCornerCenterCW(w, corner);
				break;
			}
			return;
		} else if (side < 3) {
			otherFace = faceCornerToOther[face][point][side];
			otherOrient = orientCornerToOther[point][side];
		}
	}
}

static void
faceCorners(OctWidget w, int face, int faceColor)
{
	int point;

	for (point = 0; point < 3; point++) {
		faceCorner(w, face, faceColor, point);
	}
}

static void
faceTrivialCorners(OctWidget w)
{
	int point;

	for (point = 0; point < 3; point++) {
		orientTrivialCorners(w, facesToCorner[0][point]);
	}
}

static void
allTrivialCorners(OctWidget w)
{
	int corner;

	for (corner = 0; corner < MAX_CORNERS; corner++) {
		orientTrivialCorners(w, corner);
	}
}

static Boolean
checkPiece(OctWidget w, int color, int face, int position)
{
	int newFace, newPosition, positionIndex;

	positionIndex = edgeToIndex(w, position);
	if (positionIndex == -1) {
		positionIndex = 0;
		(void) printf("position %d incorrect\n", position);
	}
	newFace = edgeMateFace[face][positionIndex];
	newPosition = indexToEdgeMate(w, positionIndex);
	return (w->oct.facetLoc[newFace][newPosition].face == color);
}

static void
findPiece(OctWidget w, int color0, int color1, int *face, int *position)
{
	int positionIndex;

	for (*face = 0; *face < MAX_FACES; (*face)++) {
		for (positionIndex = 0; positionIndex < 3; positionIndex++) {
			*position = indexToEdge(w, positionIndex);
			if (w->oct.facetLoc[*face][*position].face == color0 &&
					checkPiece(w, color1, *face, *position)) {
				return;
			}
		}
	}
	(void) printf("Piece %d %d not found!\n", color0, color1);
}

static Boolean
onFace(OctWidget w, int target, int face, int position)
{
	int side;

	if (face == target)
		return True;
	for (side = 0; side < 3; side++) {
		if (face == edgeMateFace[target][side] &&
				position == indexToEdgeMate(w, side))
			return True;
	}
	return False;
}

static Boolean
bottomRing(OctWidget w, int face, int position)
{
	return (face > 3 && position != indexToEdge(w, 2));
}

static Boolean
rightRing(OctWidget w, int face, int position)
{
	return (((face == 1 || face == 2 || face == 4 || face == 5) &&
				position == indexToEdge(w, 2)) ||
			(face == 1 && position == indexToEdge(w, 0)) ||
			(face == 2 && position == indexToEdge(w, 1)) ||
			(face == 4 && position == indexToEdge(w, 0)) ||
			(face == 5 && position == indexToEdge(w, 1)));
}

static Boolean
leftRing(OctWidget w, int face, int position)
{
	return (((face == 2 || face == 3 || face == 4 || face == 7) &&
				position == indexToEdge(w, 2)) ||
			(face == 2 && position == indexToEdge(w, 0)) ||
			(face == 3 && position == indexToEdge(w, 1)) ||
			(face == 4 && position == indexToEdge(w, 1)) ||
			(face == 7 && position == indexToEdge(w, 0)));
}

static void
face0Edge6(OctWidget w, int matchFace, int faceColor)
{
	int otherColor, face, position, matchPosition;

	matchPosition = indexToEdge(w, 2);
	/* need other color */
	face = edgeMateFace[matchFace][2];
	position = matchPosition - w->oct.size + 2; /* this is a solved piece */
	otherColor = w->oct.facetLoc[face][position].face;

	/* face and position variables are reused here */
	findPiece(w, faceColor, otherColor, &face, &position);
	if (onFace(w, 0, face, position)) { /* 1/4 of possible */
		switch (face) {
		case 0:
			if (position == indexToEdge(w, 0)) {
				rotateCornerEdgeCW(w, 4);
				rotateCornerEdgeCCW(w, 0);
				rotateCornerEdgeCCW(w, 4);
				rotateCornerEdgeCW(w, 0);
			} else if (position == indexToEdge(w, 1)) {
				rotateCornerEdgeCCW(w, 1);
				rotateCornerEdgeCW(w, 0);
				rotateCornerEdgeCW(w, 1);
				rotateCornerEdgeCCW(w, 0);
			}
			return;
		case 1:
			rotateCornerEdgeCW(w, 1);
			rotateCornerEdgeCCW(w, 4);
			rotateCornerEdgeCCW(w, 1);
			rotateCornerEdgeCW(w, 4);
			return;
		case 3:
			rotateCornerEdgeCCW(w, 4);
			rotateCornerEdgeCW(w, 1);
			rotateCornerEdgeCW(w, 4);
			rotateCornerEdgeCCW(w, 1);
			return;
		default: /* correct but flip */
			if (NRAND(2) == 0) {
				rotateCornerEdgeCW(w, 1);
				rotateCornerEdgeCW(w, 5);
				rotateCornerEdgeCCW(w, 1);
				rotateCornerEdgeCW(w, 4);
				rotateCornerEdgeCCW(w, 1);
				rotateCornerEdgeCCW(w, 4);
				rotateCornerEdgeCW(w, 1);
			} else {
				rotateCornerEdgeCCW(w, 4);
				rotateCornerEdgeCCW(w, 5);
				rotateCornerEdgeCW(w, 4);
				rotateCornerEdgeCCW(w, 1);
				rotateCornerEdgeCW(w, 4);
				rotateCornerEdgeCW(w, 1);
				rotateCornerEdgeCCW(w, 4);
			}
			return;
		}
	}
	if (leftRing(w, face, position)) {
		if ((face == 3 || face == 7) && position == indexToEdge(w, 2))
			rotateCornerEdgeCCW(w, 3);
		else if ((face == 3 && position == indexToEdge(w, 1)) ||
				(face == 2 && position == indexToEdge(w, 0)))
			rotateCornerEdgeHalf(w, 3);
		else if ((face == 2 || face == 4) && position == indexToEdge(w, 2))
			rotateCornerEdgeCW(w, 3);
	} else if (rightRing(w, face, position)) {
		if ((face == 1 || face == 5) && position == indexToEdge(w, 2))
			rotateCornerEdgeCW(w, 2);
		else if ((face == 1 && position == indexToEdge(w, 0)) ||
				(face == 2 && position == indexToEdge(w, 1)))
			rotateCornerEdgeHalf(w, 2);
		else if ((face == 2 || face == 4) && position == indexToEdge(w, 2))
			rotateCornerEdgeCCW(w, 2);
	}
	findPiece(w, faceColor, otherColor, &face, &position);
	if (!bottomRing(w, face, position)) {
		(void) printf("not in bottom ring is not possible\n");
		return;
	}
	switch (face) {
	case 4:
		rotateCornerEdgeHalf(w, 5);
		break;
	case 5:
		rotateCornerEdgeCW(w, 5);
		break;
	case 7:
		rotateCornerEdgeCCW(w, 5);
		break;
	default:
		break;
	}
	if (position == indexToEdge(w, 1)) {
		rotateCornerEdgeCCW(w, 1);
		rotateCornerEdgeCW(w, 4);
		rotateCornerEdgeCW(w, 1);
		rotateCornerEdgeCCW(w, 4);
	} else {
		rotateCornerEdgeCW(w, 4);
		rotateCornerEdgeCCW(w, 1);
		rotateCornerEdgeCCW(w, 4);
		rotateCornerEdgeCW(w, 1);
	}
}

static void
face0Edge1(OctWidget w, int matchFace, int faceColor)
{
	int otherColor, face, position;
	Boolean swap = False;

	/* need other color */
	face = edgeMateFace[matchFace][0];
	position = 2; /* this is a solved piece */
	otherColor = w->oct.facetLoc[face][position].face;

	/* face and position variables are reused here */
	findPiece(w, faceColor, otherColor, &face, &position);
	if (onFace(w, 0, face, position)) { /* 1/4 of possible */
		if (face == 0 && position == indexToEdge(w, 0)) {
			return;
		}
		if (face == 1) {
			rotateCornerEdgeCW(w, 0);
			rotateCornerEdgeCW(w, 2);
			rotateCornerEdgeCCW(w, 0);
		} else {
			rotateCornerEdgeHalf(w, 0);
			rotateCornerEdgeCW(w, 2);
			rotateCornerEdgeHalf(w, 0);
		}
		findPiece(w, faceColor, otherColor, &face, &position);
	}
	if (leftRing(w, face, position)) {
		if ((face == 3 || face == 7) && position == indexToEdge(w, 2))
			rotateCornerEdgeHalf(w, 3);
		else if ((face == 2 && position == indexToEdge(w, 0)) || face == 3)
			rotateCornerEdgeCW(w, 3);
		else if ((face == 4 && position == indexToEdge(w, 1)) || face == 7)
			rotateCornerEdgeCCW(w, 3);
		findPiece(w, faceColor, otherColor, &face, &position);
	} else if (bottomRing(w, face, position)) {
		if ((face == 7 && position == indexToEdge(w, 1)) ||
				(face == 6 && position == indexToEdge(w, 0)))
			rotateCornerEdgeHalf(w, 5);
		else if ((face == 4 && position == indexToEdge(w, 1)) ||
				(face == 7 && position == indexToEdge(w, 0)))
			rotateCornerEdgeCW(w, 5);
		else if ((face == 6 && position == indexToEdge(w, 1)) ||
				(face == 5 && position == indexToEdge(w, 0)))
			rotateCornerEdgeCCW(w, 5);
		findPiece(w, faceColor, otherColor, &face, &position);
	}
	if (!rightRing(w, face, position)) {
		(void) printf("not in rightRing is not possible\n");
		return;
	}
	switch (face) {
	case 2:
		rotateCornerEdgeCW(w, 2);
		swap = True;
		break;
	case 4:
		rotateCornerEdgeHalf(w, 2);
		break;
	case 5:
		rotateCornerEdgeCCW(w, 2);
		swap = True;
		break;
	default:
		break;
	}
	if ((position == indexToEdge(w, 2) && !swap) || (position != indexToEdge(w, 2) && swap)) {
		rotateCornerEdgeCW(w, 1);
		rotateCornerEdgeCCW(w, 0);
		rotateCornerEdgeCCW(w, 1);
		rotateCornerEdgeCW(w, 0);
	} else {
		rotateCornerEdgeCCW(w, 0);
		rotateCornerEdgeCW(w, 1);
		rotateCornerEdgeCW(w, 0);
		rotateCornerEdgeCCW(w, 1);
	}
}

static void
face0Edge3(OctWidget w, int matchFace, int faceColor)
{
	int otherColor, face, position;
	Boolean swap = False;

	/* need other color */
	face = edgeMateFace[matchFace][1];
	position = 2; /* this is a solved piece */
	otherColor = w->oct.facetLoc[face][position].face;

	/* face and position variables are reused here */
	findPiece(w, faceColor, otherColor, &face, &position);
	if (onFace(w, 0, face, position)) { /* 1/4 of possible */
		if (face == 0 && position == indexToEdge(w, 1)) {
			return;
		}
		/* face == 3 */
		rotateCornerEdgeCCW(w, 0);
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCW(w, 0);
		findPiece(w, faceColor, otherColor, &face, &position);
	}
	if (rightRing(w, face, position)) {
		if ((face == 1 || face == 5) && position == indexToEdge(w, 2))
			rotateCornerEdgeHalf(w, 2);
		else if ((face == 2 && position == indexToEdge(w, 1)) || face == 1)
			rotateCornerEdgeCCW(w, 2);
		else if ((face == 4 && position == indexToEdge(w, 0)) || face == 5)
			rotateCornerEdgeCW(w, 2);
		findPiece(w, faceColor, otherColor, &face, &position);
	} else if (bottomRing(w, face, position)) {
		if ((face == 5 && position == indexToEdge(w, 0)) ||
				(face == 6 && position == indexToEdge(w, 1)))
			rotateCornerEdgeHalf(w, 5);
		else if ((face == 4 && position == indexToEdge(w, 0)) ||
				(face == 5 && position == indexToEdge(w, 1))) {
			rotateCornerEdgeCCW(w, 5);
		} else if ((face == 6 && position == indexToEdge(w, 0)) ||
				(face == 7 && position == indexToEdge(w, 1))) {
			rotateCornerEdgeCW(w, 5);
		}
		findPiece(w, faceColor, otherColor, &face, &position);
	}
	if (!leftRing(w, face, position)) {
		(void) printf("not in leftRing is not possible\n");
		return;
	}
	switch (face) {
	case 2:
		rotateCornerEdgeCCW(w, 3);
		swap = True;
		break;
	case 4:
		rotateCornerEdgeHalf(w, 3);
		break;
	case 7:
		rotateCornerEdgeCW(w, 3);
		swap = True;
		break;
	default:
		break;
	}
	if ((position == indexToEdge(w, 2) && !swap) || (position != indexToEdge(w, 2) && swap)) {
		rotateCornerEdgeCCW(w, 4);
		rotateCornerEdgeCW(w, 0);
		rotateCornerEdgeCW(w, 4);
		rotateCornerEdgeCCW(w, 0);
	} else {
		rotateCornerEdgeCW(w, 0);
		rotateCornerEdgeCCW(w, 4);
		rotateCornerEdgeCCW(w, 0);
		rotateCornerEdgeCW(w, 4);
	}
}

static void
face1Edge6(OctWidget w, int matchFace, int faceColor)
{
	int otherColor, face, position, matchPosition;

	matchPosition = indexToEdge(w, 2);
	/* need other color */
	face = edgeMateFace[matchFace][2];
	position = matchPosition - w->oct.size + 2; /* this is a solved piece */
	otherColor = w->oct.facetLoc[face][position].face;

	/* face and position variables are reused here */
	findPiece(w, faceColor, otherColor, &face, &position);
	if (onFace(w, 1, face, position)) {
		if (face == 1 && position == indexToEdge(w, 2)) {
			return;
		}
		if (face == 5 && position == indexToEdge(w, 2)) {
			rotateCornerEdgeCW(w, 2);
			rotateCornerEdgeCW(w, 5);
			rotateCornerEdgeCCW(w, 2);
		} else {
			rotateCornerEdgeHalf(w, 2);
			rotateCornerEdgeCW(w, 5);
			rotateCornerEdgeHalf(w, 2);
		}
		findPiece(w, faceColor, otherColor, &face, &position);
	} else if (leftRing(w, face, position)) {
		if ((face == 3 || face == 7) && position == indexToEdge(w, 2)) {
			rotateCornerEdgeCCW(w, 3);
		} else if ((face == 2 || face == 4) && position == indexToEdge(w, 2)) {
			rotateCornerEdgeCW(w, 3);
		} else if ((face == 3 && position == indexToEdge(w, 1)) ||
				(face == 2 && position == indexToEdge(w, 0))) {
			rotateCornerEdgeHalf(w, 3);
		}
		findPiece(w, faceColor, otherColor, &face, &position);
	}
	if (!bottomRing(w, face, position)) {
		(void) printf("not in bottomRing is not possible\n");
		return;
	}
	switch (face) {
	case 4:
		rotateCornerEdgeCW(w, 5);
		break;
	case 6:
		rotateCornerEdgeCCW(w, 5);
		break;
	case 7:
		rotateCornerEdgeHalf(w, 5);
		break;
	default:
		break;
	}
	if (position == indexToEdge(w, 0)) {
		rotateCornerEdgeCW(w, 1);
		rotateCornerEdgeCCW(w, 2);
		rotateCornerEdgeCCW(w, 1);
		rotateCornerEdgeCW(w, 2);
	} else {
		rotateCornerEdgeCCW(w, 2);
		rotateCornerEdgeCW(w, 1);
		rotateCornerEdgeCW(w, 2);
		rotateCornerEdgeCCW(w, 1);
	}
}

static void
face1Edge1(OctWidget w, int matchFace, int faceColor)
{
	int otherColor, face, position;
	Boolean swap = False;

	/* need other color */
	face = edgeMateFace[matchFace][0];
	position = 2; /* this is a solved piece */
	otherColor = w->oct.facetLoc[face][position].face;

	/* face and position variables are reused here */
	findPiece(w, faceColor, otherColor, &face, &position);
	if (onFace(w, 1, face, position)) {
		if (face == 1 && position == indexToEdge(w, 0)) {
			return;
		}
		rotateCornerEdgeCCW(w, 2);
		rotateCornerEdgeCW(w, 3);
		rotateCornerEdgeCW(w, 2);
		findPiece(w, faceColor, otherColor, &face, &position);
	} else if (bottomRing(w, face, position)) {
		if ((face == 4 && position == indexToEdge(w, 0)) ||
				(face == 5 && position == indexToEdge(w, 1))) {
			rotateCornerEdgeCCW(w, 5);
		} else if ((face == 5 && position == indexToEdge(w, 0)) ||
				(face == 6 && position == indexToEdge(w, 1))) {
			rotateCornerEdgeHalf(w, 5);
		} else if ((face == 6 && position == indexToEdge(w, 0)) ||
				(face == 7 && position == indexToEdge(w, 1))) {
			rotateCornerEdgeCW(w, 5);
		}
		findPiece(w, faceColor, otherColor, &face, &position);
	}
	if (!leftRing(w, face, position)) {
		(void) printf("not in leftRing is not possible\n");
		return;
	}
	switch (face) {
	case 3:
		rotateCornerEdgeCW(w, 3);
		swap = True;
		break;
	case 4:
		rotateCornerEdgeCCW(w, 3);
		swap = True;
		break;
	case 7:
		rotateCornerEdgeHalf(w, 3);
		break;
	default:
		break;
	}
	if ((position == indexToEdge(w, 2) && !swap)
			|| (position != indexToEdge(w, 2) && swap)) {
		rotateCornerEdgeCW(w, 2);
		rotateCornerEdgeCCW(w, 0);
		rotateCornerEdgeCCW(w, 2);
		rotateCornerEdgeCW(w, 0);
	} else {
		rotateCornerEdgeCCW(w, 0);
		rotateCornerEdgeCW(w, 2);
		rotateCornerEdgeCW(w, 0);
		rotateCornerEdgeCCW(w, 2);
	}
}

static void
face3Edge6(OctWidget w, int matchFace, int faceColor)
{
	int otherColor, face, position, matchPosition;

	matchPosition = indexToEdge(w, 2);
	/* need other color */
	face = edgeMateFace[matchFace][2];
	position = matchPosition - w->oct.size + 2; /* this is a solved piece */
	otherColor = w->oct.facetLoc[face][position].face;

	/* face and position variables are reused here */
	findPiece(w, faceColor, otherColor, &face, &position);
	if (leftRing(w, face, position)) {
		if (face == 3 && position == indexToEdge(w, 2)) {
			return;
		}
		if (face == 7 && position == indexToEdge(w, 2)) {
			rotateCornerEdgeCCW(w, 3);
			rotateCornerEdgeCCW(w, 5);
			rotateCornerEdgeCW(w, 3);
		} else if ((face == 3 && position == indexToEdge(w, 1)) ||
				(face == 2 && position == indexToEdge(w, 0))) {
			rotateCornerEdgeHalf(w, 3);
			rotateCornerEdgeCCW(w, 5);
			rotateCornerEdgeHalf(w, 3);
		} else if ((face == 2 || face == 4) && position == indexToEdge(w, 2)) {
			rotateCornerEdgeCW(w, 3);
			rotateCornerEdgeCCW(w, 5);
			rotateCornerEdgeCCW(w, 3);
		}
		findPiece(w, faceColor, otherColor, &face, &position);
	}
	if (!bottomRing(w, face, position)) {
		(void) printf("not in bottomRing is not possible\n");
		return;
	}
	switch (face) {
	case 4:
		rotateCornerEdgeCCW(w, 5);
		break;
	case 5:
		rotateCornerEdgeHalf(w, 5);
		break;
	case 6:
		rotateCornerEdgeCW(w, 5);
		break;
	default:
		break;
	}
	if (position == indexToEdge(w, 0)) {
		rotateCornerEdgeCW(w, 3);
		rotateCornerEdgeCCW(w, 4);
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCW(w, 4);
	} else {
		rotateCornerEdgeCCW(w, 4);
		rotateCornerEdgeCW(w, 3);
		rotateCornerEdgeCW(w, 4);
		rotateCornerEdgeCCW(w, 3);
	}
}

static void
face3Edge3(OctWidget w, int matchFace, int faceColor)
{
	int otherColor, face, position;

	/* need other color */
	face = edgeMateFace[matchFace][1];
	position = 2; /* this is a solved piece */
	otherColor = w->oct.facetLoc[face][position].face;

	/* face and position variables are reused here */
	findPiece(w, faceColor, otherColor, &face, &position);
	if (leftRing(w, face, position)) {
		if (face == 3 && position == indexToEdge(w, 1)) {
			return;
		}
		if (face == 2 && position == indexToEdge(w, 0)) {
			rotateCornerEdgeHalf(w, 3);
			rotateCornerEdgeCW(w, 5);
			rotateCornerEdgeHalf(w, 3);
		} else if (position == indexToEdge(w, 2)) {
			rotateCornerEdgeCW(w, 3);
			rotateCornerEdgeCW(w, 5);
			rotateCornerEdgeCCW(w, 3);
		} else {
			rotateCornerEdgeCW(w, 5);
		}
		findPiece(w, faceColor, otherColor, &face, &position);
	}
	if (!bottomRing(w, face, position)) {
		(void) printf("not in bottomRing is not possible\n");
		return;
	}
	rotateCornerEdgeCW(w, 3);
	switch (face) {
	case 5:
		rotateCornerEdgeCCW(w, 5);
		break;
	case 6:
		rotateCornerEdgeHalf(w, 5);
		break;
	case 7:
		rotateCornerEdgeCW(w, 5);
		break;
	default:
		break;
	}
	if (position == indexToEdge(w, 0)) {
		rotateCornerEdgeCW(w, 2);
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCCW(w, 2);
		rotateCornerEdgeCW(w, 3);
	} else {
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCW(w, 2);
		rotateCornerEdgeCW(w, 3);
		rotateCornerEdgeCCW(w, 2);
	}
	rotateCornerEdgeCCW(w, 3);
}

static void
face2Edge6(OctWidget w, int matchFace, int faceColor)
{
	int otherColor, face, position, matchPosition;

	matchPosition = indexToEdge(w, 2);
	/* need other color */
	face = edgeMateFace[matchFace][2];
	position = matchPosition - w->oct.size + 2; /* this is a solved piece */
	otherColor = w->oct.facetLoc[face][position].face;

	/* face and position variables are reused here */
	findPiece(w, faceColor, otherColor, &face, &position);
	if (leftRing(w, face, position)) {
		if (face == 2 && position == indexToEdge(w, 2)) {
			return;
		}
		rotateCornerEdgeCW(w, 3);
		rotateCornerEdgeCCW(w, 5);
		rotateCornerEdgeCCW(w, 3);
		findPiece(w, faceColor, otherColor, &face, &position);
	}
	if (!bottomRing(w, face, position)) {
		(void) printf("not in bottomRing is not possible\n");
		return;
	}
	switch (face) {
	case 5:
		rotateCornerEdgeCCW(w, 5);
		break;
	case 6:
		rotateCornerEdgeHalf(w, 5);
		break;
	case 7:
		rotateCornerEdgeCW(w, 5);
		break;
	default:
		break;
	}
	if (position == indexToEdge(w, 0)) {
		rotateCornerEdgeCW(w, 2);
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCCW(w, 2);
		rotateCornerEdgeCW(w, 3);
	} else {
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCW(w, 2);
		rotateCornerEdgeCW(w, 3);
		rotateCornerEdgeCCW(w, 2);
	}
}

static void
face4Edge1(OctWidget w, int matchFace, int faceColor)
{
	int otherColor, face, position;

	/* need other color */
	face = edgeMateFace[matchFace][0];
	position = 2; /* this is a solved piece */
	otherColor = w->oct.facetLoc[face][position].face;

	/* face and position variables are reused here */
	findPiece(w, faceColor, otherColor, &face, &position);
	if (!bottomRing(w, face, position)) {
		(void) printf("not in bottomRing is not possible\n");
		return;
	}
	if (face == 4 && position == indexToEdge(w, 0)) {
		return;
	}
	/* try rotating puzzle in case of solved pieces */
	if ((w->oct.facetLoc[4][indexToEdge(w, 1)].face ==
			w->oct.facetLoc[4][2].face) &&
			(w->oct.facetLoc[7][indexToEdge(w, 0)].face ==
			w->oct.facetLoc[7][2].face)) {
		rotatePuzzleCW(w, 5);
		return;
	} else if ((w->oct.facetLoc[6][indexToEdge(w, 1)].face ==
			w->oct.facetLoc[6][2].face) &&
			(w->oct.facetLoc[5][indexToEdge(w, 0)].face ==
			w->oct.facetLoc[5][2].face)) {
		rotatePuzzleCCW(w, 5);
		return;
	} else if ((w->oct.facetLoc[7][indexToEdge(w, 1)].face ==
			w->oct.facetLoc[7][2].face) &&
			(w->oct.facetLoc[6][indexToEdge(w, 0)].face ==
			w->oct.facetLoc[6][2].face)) {
		rotatePuzzleHalf(w, 5);
		return;
	}
	if (face == 4 && position == indexToEdge(w, 1)) {
		rotateCornerEdgeCW(w, 1);
		rotateCornerEdgeCW(w, 2);
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCW(w, 2);
		rotateCornerEdgeCW(w, 3);
		rotateCornerEdgeHalf(w, 2);
		rotateCornerEdgeCCW(w, 1);
	} else if (face == 5 && position == indexToEdge(w, 0)) {
		rotateCornerEdgeCW(w, 1);
		rotateCornerEdgeCW(w, 2);
		rotateCornerEdgeCW(w, 3);
		rotateCornerEdgeCCW(w, 5);
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCW(w, 5);
		rotateCornerEdgeCCW(w, 2);
		rotateCornerEdgeCCW(w, 1);
	} else if (face == 5 && position == indexToEdge(w, 1)) {
		rotateCornerEdgeCW(w, 1);
		rotateCornerEdgeHalf(w, 2);
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCCW(w, 2);
		rotateCornerEdgeCW(w, 3);
		rotateCornerEdgeCCW(w, 2);
		rotateCornerEdgeCW(w, 5);
		rotateCornerEdgeCW(w, 2);
		rotateCornerEdgeCCW(w, 5);
		rotateCornerEdgeCCW(w, 2);
		rotateCornerEdgeCCW(w, 1);
	} else if (face == 6 && position == indexToEdge(w, 0)) {
		rotateCornerEdgeCCW(w, 4);
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCW(w, 2);
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCCW(w, 2);
		rotateCornerEdgeHalf(w, 3);
		rotateCornerEdgeCW(w, 4);
	} else if (face == 6 && position == indexToEdge(w, 1)) {
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCCW(w, 2);
		rotateCornerEdgeCW(w, 1);
		rotateCornerEdgeCCW(w, 2);
		rotateCornerEdgeCCW(w, 1);
		rotateCornerEdgeHalf(w, 2);
		rotateCornerEdgeCW(w, 3);
	} else if (face == 7 && position == indexToEdge(w, 0)) {
		rotateCornerEdgeCW(w, 1);
		/*rotateCornerEdgeCW(w, 2);
		rotateCornerEdgeCCW(w, 2);*/
		rotateCornerEdgeCW(w, 5);
		rotateCornerEdgeCW(w, 2);
		rotateCornerEdgeCCW(w, 5);
		rotateCornerEdgeCCW(w, 2);
		rotateCornerEdgeCCW(w, 1);
	} else if (face == 7 && position == indexToEdge(w, 1)) {
		rotateCornerEdgeCCW(w, 4);
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCW(w, 5);
		rotateCornerEdgeCCW(w, 2);
		rotateCornerEdgeCCW(w, 5);
		rotateCornerEdgeCW(w, 2);
		rotateCornerEdgeCW(w, 3);
		rotateCornerEdgeCW(w, 4);
	}
}

static int lastCount = 0;
static void solveLastCorner(OctWidget w);

static void
lastEdges(OctWidget w, int matchFace0, int faceColor0,
		int matchFace1, int faceColor1)
{
	int otherColor, face0, position0, face1, position1;

	/* need other color */
	face0 = edgeMateFace[matchFace0][1];
	position0 = 2; /* this is a solved piece */
	otherColor = w->oct.facetLoc[face0][position0].face;

	/* face and position variables are reused here */
	findPiece(w, faceColor0, otherColor, &face0, &position0);

	/* need other color */
	face1 = edgeMateFace[matchFace1][0];
	position1 = 2; /* this is a solved piece */
	otherColor = w->oct.facetLoc[face1][position1].face;

	/* face and position variables are reused here */
	findPiece(w, faceColor1, otherColor, &face1, &position1);

	/* 12 possibilities */
	if (face0 == 4 && position0 == indexToEdge(w, 1)
			&& face1 == 5 && position1 == indexToEdge(w, 0)) {
#ifdef DEBUG
		(void) printf("done\n");
#endif
		return;
	}
	if (face0 == 4 && position0 == indexToEdge(w, 1) &&
			face1 == 6 && position1 == indexToEdge(w, 1)) {
#ifdef DEBUG
		(void) printf("4363!\n");
#endif
		rotateCornerEdgeCCW(w, 1);
		rotateCornerEdgeCW(w, 4);
		rotateCornerEdgeCW(w, 1);
		rotateCornerEdgeCCW(w, 4);
		rotateCornerEdgeCW(w, 5);
		rotateCornerEdgeCCW(w, 4);
		rotateCornerEdgeCCW(w, 5);
		rotateCornerEdgeCW(w, 4);
	} else if (face0 == 5 && position0 == indexToEdge(w, 0) &&
			face1 == 6 && position1 == indexToEdge(w, 0)) {
#ifdef DEBUG
		(void) printf("5161!\n");
#endif
		rotateCornerEdgeCCW(w, 1);
		rotateCornerEdgeCCW(w, 4);
		rotateCornerEdgeCW(w, 5);
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCCW(w, 5);
		rotateCornerEdgeCW(w, 3);
		rotateCornerEdgeCW(w, 4);
		rotateCornerEdgeCW(w, 1);
	} else if (face0 == 5 && position0 == indexToEdge(w, 0) &&
			face1 == 7 && position1 == indexToEdge(w, 1)) {
#ifdef DEBUG
		(void) printf("5173!\n");
#endif
		rotateCornerEdgeCCW(w, 1);
		/*rotateCornerEdgeCCW(w, 4);
		rotateCornerEdgeCW(w, 4);*/
		rotateCornerEdgeCCW(w, 5);
		rotateCornerEdgeCCW(w, 4);
		rotateCornerEdgeCW(w, 5);
		rotateCornerEdgeCW(w, 4);
		rotateCornerEdgeCW(w, 1);
	} else if (face0 == 6 && position0 == indexToEdge(w, 0) &&
			face1 == 4 && position1 == indexToEdge(w, 1)) {
#ifdef DEBUG
		(void) printf("6143!\n");
#endif
		rotateCornerEdgeCCW(w, 1);
		rotateCornerEdgeCCW(w, 4);
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCW(w, 5);
		rotateCornerEdgeCW(w, 3);
		rotateCornerEdgeCCW(w, 5);
		rotateCornerEdgeCW(w, 4);
		rotateCornerEdgeCW(w, 1);
	} else if (face0 == 6 && position0 == indexToEdge(w, 0) &&
			face1 == 7 && position1 == indexToEdge(w, 0)) {
#ifdef DEBUG
		(void) printf("6171!\n");
#endif
		rotateCornerEdgeCCW(w, 1);
		rotateCornerEdgeHalf(w, 4);
		rotateCornerEdgeCW(w, 3);
		rotateCornerEdgeCW(w, 4);
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCW(w, 4);
		rotateCornerEdgeCW(w, 1);
	} else if (face0 == 6 && position0 == indexToEdge(w, 1) &&
			face1 == 6 && position1 == indexToEdge(w, 0)) {
#ifdef DEBUG
		(void) printf("6361!\n");
#endif
		rotateCornerEdgeCW(w, 3);
		rotateCornerEdgeCW(w, 5);
		rotateCornerEdgeCW(w, 4);
		rotateCornerEdgeHalf(w, 5);
		rotateCornerEdgeCW(w, 1);
		rotateCornerEdgeCW(w, 5);
		rotateCornerEdgeCCW(w, 1);
		rotateCornerEdgeCCW(w, 4);
		rotateCornerEdgeCCW(w, 3);
	} else if (face0 == 6 && position0 == indexToEdge(w, 1) &&
			face1 == 7 && position1 == indexToEdge(w, 1)) {
#ifdef DEBUG
		(void) printf("6373!\n");
#endif
		rotateCornerEdgeCCW(w, 1);
		rotateCornerEdgeCCW(w, 4);
		rotateCornerEdgeCW(w, 3);
		rotateCornerEdgeCCW(w, 4);
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeHalf(w, 4);
		rotateCornerEdgeCW(w, 1);
	} else if (face0 == 7 && position0 == indexToEdge(w, 0) &&
			face1 == 5 && position1 == indexToEdge(w, 0)) {
#ifdef DEBUG
		(void) printf("7151!\n");
#endif
		rotateCornerEdgeCCW(w, 4);
		rotateCornerEdgeCW(w, 3);
		rotateCornerEdgeCW(w, 4);
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCW(w, 5);
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCCW(w, 5);
		rotateCornerEdgeCW(w, 3);
	} else if (face0 == 7 && position0 == indexToEdge(w, 0) &&
			face1 == 6 && position1 == indexToEdge(w, 1)) {
#ifdef DEBUG
		(void) printf("7163!\n");
#endif
		rotateCornerEdgeCCW(w, 1);
		rotateCornerEdgeHalf(w, 4);
		rotateCornerEdgeCW(w, 3);
		rotateCornerEdgeCW(w, 4);
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCW(w, 5);
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCCW(w, 5);
		rotateCornerEdgeCW(w, 3);
		rotateCornerEdgeCW(w, 4);
		rotateCornerEdgeCW(w, 1);
	} else if (face0 == 7 && position0 == indexToEdge(w, 1) &&
			face1 == 4 && position1 == indexToEdge(w, 1)) {
#ifdef DEBUG
		(void) printf("7343!\n");
#endif
		rotateCornerEdgeCCW(w, 1);
		rotateCornerEdgeCCW(w, 4);
		rotateCornerEdgeCCW(w, 5);
		rotateCornerEdgeCW(w, 4);
		rotateCornerEdgeCW(w, 5);
		rotateCornerEdgeCW(w, 1);
	} else if (face0 == 7 && position0 == indexToEdge(w, 1) &&
			face1 == 7 && position1 == indexToEdge(w, 0)) {
#ifdef DEBUG
		(void) printf("7371!\n");
#endif
		rotateCornerEdgeCCW(w, 1);
		rotateCornerEdgeCCW(w, 5);
		rotateCornerEdgeCCW(w, 4);
		rotateCornerEdgeHalf(w, 5);
		rotateCornerEdgeCCW(w, 3);
		rotateCornerEdgeCCW(w, 5);
		rotateCornerEdgeCW(w, 3);
		rotateCornerEdgeCW(w, 4);
		rotateCornerEdgeCW(w, 1);
	} else {
		if (lastCount == 0) {
			lastCount++;
			if (NRAND(2) == 0)
				rotateCornerEdgeCW(w, 5);
			else
				rotateCornerEdgeCCW(w, 5);
#ifdef DEBUG
			(void) printf("try last part again\n");
#endif
			solveLastCorner(w);
		} else
			(void) printf("13th case, not possible %d%d%d%d\n",
				face0, position0, face1, position1);
	}
}

static void
solveTopFace(OctWidget w)
{
	/* Pick a face (0) and determine which color is present at each
	 * corner. */
	int topFace = 0;
	int faceColor = findFaceColor(w, topFace);

	faceCorners(w, topFace, faceColor);
	faceTrivialCorners(w);
	face0Edge6(w, topFace, faceColor);
	face0Edge1(w, topFace, faceColor);
	face0Edge3(w, topFace, faceColor);
}

static void
solveSecondFace(OctWidget w)
{
	int rightFace = 1;
	int faceColor = findFaceColor(w, rightFace);

	faceCorner(w, rightFace, faceColor, 1);
	orientTrivialCorners(w, facesToCorner[1][1]);
	face1Edge6(w, rightFace, faceColor);
	face1Edge1(w, rightFace, faceColor);
}

static void
solveThirdCorner(OctWidget w)
{
	int leftFace = 3, bottomFace = 2;
	int faceColor = findFaceColor(w, leftFace);

	faceCorner(w, leftFace, faceColor, 2);
	orientTrivialCorners(w, facesToCorner[3][2]);
	face3Edge6(w, leftFace, faceColor);
	face3Edge3(w, leftFace, faceColor);
	faceColor = findFaceColor(w, bottomFace);
	face2Edge6(w, bottomFace, faceColor);
}

static void
solveLastCorner(OctWidget w)
{
	int bottomFace = 4, rightFace = 5;
	int faceColor0 = findFaceColor(w, bottomFace), faceColor1;

	faceCorner(w, bottomFace, faceColor0, 0);
	orientTrivialCorners(w, facesToCorner[5][0]);
	/* Now for the hard part... last 4 */
	face4Edge1(w, bottomFace, faceColor0);
	/* Also relatively hard, redo in case rotated */
	faceColor0 = findFaceColor(w, bottomFace);
	faceColor1 = findFaceColor(w, rightFace);
	lastEdges(w, bottomFace, faceColor0, rightFace, faceColor1);
}

/* Size 4 oct */
/* switch 2 and 3 so can have odd and even have a parity meaning for edgesLR */
static void
printFacets(OctWidget w)
{
	int face, position, square;

	for (face = 0; face < MAX_FACES; face++) {
		square = 1;
		for (position = 0; position < w->oct.sizeSize; position++) {
			(void) printf("%d %d  ",
				w->oct.facetLoc[face][position].face,
				w->oct.facetLoc[face][position].rotation);
			if (position == square * square - 1) {
				(void) printf("\n");
				++square;
			}
		}
		(void) printf("\n");
	}
	(void) printf("\n");
}

static int edgeLRMateFace[MAX_FACES][6] =
{
	{1, 3, 3, 1, 6, 6},
	{2, 0, 0, 2, 5, 5},
	{3, 1, 1, 3, 4, 4},
	{0, 2, 2, 0, 7, 7},
	{5, 7, 7, 5, 2, 2},
	{6, 4, 4, 6, 1, 1},
	{7, 5, 5, 7, 0, 0},
	{0, 6, 6, 0, 3, 3}
};

static int edgeLRMatePositionIndex[6] =
{1, 0, 3, 2, 5, 4};

static int
indexToEdgeLR(OctWidget w, int edgeIndex)
{
	switch (edgeIndex) { /* Size 4 Oct -> 1, 3, 4, 8, 11, 13 */
	case 0:
		return 1;
	case 1:
		return 3;
	case 3:
		return (w->oct.size - 2) * (w->oct.size - 2);
	case 2:
		return (w->oct.size - 1) * (w->oct.size - 1) - 1;
	case 4:
		return (w->oct.size - 1) * (w->oct.size - 1) + 2;
	case 5:
		return w->oct.size * w->oct.size - 3;
	default:
		(void) printf("edge unknown %d\n", edgeIndex);
	}
	return -1;
}

static int
edgeLRToIndex(OctWidget w, int edge)
{
	int temp; /* Size 4 Oct -> {-1, 0, -1, 1, 3, -1, -1, -1, 2, -1, -1, 4, -1, 5, -1, -1} */

	if (edge == 1)
		return 0;
	else if (edge == 3)
		return 1;
	temp = (w->oct.size - 1) * (w->oct.size - 1) - 1 - edge;
	if (temp == 0)
		return 2;
	else if (temp > 0) {
		temp = (w->oct.size - 2) * (w->oct.size - 2) - edge;
		if (temp == 0)
			return 3;
	} else if (temp < 0) {
		if (temp == -3)
			return 4;
		temp = w->oct.size * w->oct.size - 3 - edge;
		if (temp == 0)
			return 5;
	}
	return -1;
}

static Boolean
checkPieceLR(OctWidget w, int color, int face, int position)
{
	int newFace, newPosition, positionIndex, newPositionIndex;

	positionIndex = edgeLRToIndex(w, position);
	if (positionIndex == -1) {
		positionIndex = 0;
		(void) printf("position %d incorrect\n", position);
	}
	newFace = edgeLRMateFace[face][positionIndex];
	newPositionIndex = edgeLRMatePositionIndex[positionIndex];
	newPosition = indexToEdgeLR(w, newPositionIndex);
	return (w->oct.facetLoc[newFace][newPosition].face == color);
}

/* color0 is even position */
static void
findPieceLR(OctWidget w, int color0, int color1, int *face, int *position)
{
	int faceSkip, positionIndex, startPositionIndex;

	startPositionIndex = edgeLRToIndex(w, *position);
	/* Check starting face first */
	for (positionIndex = 0; positionIndex < 6; positionIndex++) {
		*position = indexToEdgeLR(w, positionIndex);
		if (((startPositionIndex + positionIndex) % 2) == 0) {
			if (w->oct.facetLoc[*face][*position].face == color0 &&
					checkPieceLR(w, color1, *face, *position)) {
#ifdef DEBUG
				(void) printf("LRe %d %d\n", *face, *position);
#endif
				return;
			}
		} else {
			if (w->oct.facetLoc[*face][*position].face == color1 &&
					checkPieceLR(w, color0, *face, *position)) {
#ifdef DEBUG
				(void) printf("LRo %d %d\n", *face, *position);
#endif
				return;
			}
		}
	}
	faceSkip = *face;
	for (*face = 0; *face < MAX_FACES; (*face)++) {
		if (*face == faceSkip)
			continue;
		for (positionIndex = 0; positionIndex < 6; positionIndex++) {
			*position = indexToEdgeLR(w, positionIndex);
			if (((startPositionIndex + positionIndex) % 2) == 0) {
				if (w->oct.facetLoc[*face][*position].face == color0 &&
						checkPieceLR(w, color1, *face, *position)) {
#ifdef DEBUG
					(void) printf("LR e %d %d\n", *face, *position);
#endif
					return;
				}
			} else {
				if (w->oct.facetLoc[*face][*position].face == color1 &&
						checkPieceLR(w, color0, *face, *position)) {
#ifdef DEBUG
					(void) printf("LR o %d %d\n", *face, *position);
#endif
					return;
				}
			}
		}
	}
	(void) printf("PieceLR %d %d not found!\n", color0, color1);
	printFacets(w);
}

static void
solve0LR0(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[0][0].face;
	int color1 = w->oct.facetLoc[1][0].face;
	int startFace = 0, startPositionIndex = 0;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 0LR0 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
		switch (positionIndex) {
		case 0:
			return;
		case 1:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			return;
		case 4:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			return;
		}
		break;
	case 1:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			return;
		case 4:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				TR, PERIOD4, FALSE);
			return;
		}
		break;
	case 2:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			return;
		case 4:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			return;
		}
		break;
	case 3:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			return;
		}
		break;
	case 4:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			return;
		case 1:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 1),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 1),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			return;
		}
		break;
	case 5:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				TR, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			return;
		}
		break;
	case 6:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			return;
		}
		break;
	}
}

static void
solve0LR1(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[0][0].face;
	int color1 = w->oct.facetLoc[3][0].face;
	int startFace = 0, startPositionIndex = 1;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 0LR1 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
		switch (positionIndex) {
		case 0:
			(void) printf("cannot happen\n");
			return;
		case 1:
			return;
		case 2:
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			return;
		case 4:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			return;
		}
		break;
	case 1:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			return;
		case 4:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			return;
		}
		break;
	case 2:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			return;
		case 4:
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 1),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 1),
				BR, PERIOD4, FALSE);
			return;
		}
		break;
	case 3:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				TL, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			return;
		}
		break;
	case 4:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			return;
		case 1:
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 1),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 1),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 1),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 1),
				TL, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			return;
		}
		break;
	case 5:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			return;
		}
		break;
	case 6:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			return;
		}
		break;
	}
}

static void
solve0LR2(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[0][0].face;
	int color1 = w->oct.facetLoc[3][0].face;
	int startFace = 0, startPositionIndex = 2;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 0LR2 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
		switch (positionIndex) {
		case 0:
		case 1:
			(void) printf("cannot happen\n");
			return;
		case 2:
			return;
		case 3:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			return;
		case 4:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			return;
		}
		break;
	case 1:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			return;
		case 4:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			return;
		}
		break;
	case 2:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			return;
		case 4:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			return;
		}
		break;
	case 3:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			return;
		}
		break;
	case 4:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			return;
		case 1:
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			return;
		}
		break;
	case 5:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			return;
		}
		break;
	case 6:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			return;
		}
		break;
	}
}

static void
solve0LR3(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[0][0].face;
	int color1 = w->oct.facetLoc[1][0].face;
	int startFace = 0, startPositionIndex = 3;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 0LR3 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
		switch (positionIndex) {
		case 0:
		case 1:
		case 2:
			(void) printf("cannot happen\n");
			return;
		case 3:
			return;
		case 4:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			return;
		}
		break;
	case 1:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			return;
		case 4:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			return;
		}
		break;
	case 2:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			return;
		case 4:
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			return;
		}
		break;
	case 3:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			return;
		}
		break;
	case 4:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			return;
		case 1:
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			return;
		}
		break;
	case 5:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			return;
		}
		break;
	case 6:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			return;
		}
		break;
	}
}

static void
solve2LR0(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[2][0].face;
	int color1 = w->oct.facetLoc[3][0].face;
	int startFace = 2, startPositionIndex = 0;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 2LR0 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
		switch (positionIndex) {
		case 0:
		case 1:
		case 2:
		case 3:
			(void) printf("cannot happen\n");
			return;
		case 4:
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 0),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 0),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			return;
		}
		break;
	case 1:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			return;
		}
		break;
	case 2:
		switch (positionIndex) {
		case 0:
			return;
		case 1:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			return;
		case 4:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			return;
		}
		break;
	case 3:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 0),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 0),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			return;
		}
		break;
	case 4:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			return;
		case 1:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			return;
		}
		break;
	case 5:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 0),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 0),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			return;
		}
		break;
	case 6:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 0),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 0),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			return;
		}
		break;
	}
}

static void
solve2LR1(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[2][0].face;
	int color1 = w->oct.facetLoc[1][0].face;
	int startFace = 2, startPositionIndex = 1;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 2LR1 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
		switch (positionIndex) {
		case 0:
		case 1:
		case 2:
		case 3:
			(void) printf("cannot happen\n");
			return;
		case 4:
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			return;
		}
		break;
	case 1:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 0),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 0),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			return;
		}
		break;
	case 2:
		switch (positionIndex) {
		case 0:
			(void) printf("cannot happen\n");
			return;
		case 1:
			return;
		case 2:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			return;
		case 4:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			return;
		}
		break;
	case 3:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			return;
		}
		break;
	case 4:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			return;
		case 1:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			return;
		}
		break;
	case 5:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			return;
		}
		break;
	case 6:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			return;
		}
		break;
	}
}

static void
solve2LR2(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[2][0].face;
	int color1 = w->oct.facetLoc[1][0].face;
	int startFace = 2, startPositionIndex = 2;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 2LR2 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
		switch (positionIndex) {
		case 0:
		case 1:
		case 2:
		case 3:
			(void) printf("cannot happen\n");
			return;
		case 4:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 1, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			return;
		}
		break;
	case 1:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			return;
		}
		break;
	case 2:
		switch (positionIndex) {
		case 0:
		case 1:
			(void) printf("cannot happen\n");
			return;
		case 2:
			return;
		case 3:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			return;
		case 4:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			return;
		}
		break;
	case 3:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			return;
		}
		break;
	case 4:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			return;
		case 1:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			return;
		}
		break;
	case 5:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			return;
		}
		break;
	case 6:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			return;
		}
		break;
	}
}

static void
solve2LR3(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[2][0].face;
	int color1 = w->oct.facetLoc[3][0].face;
	int startFace = 2, startPositionIndex = 3;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 2LR3 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
		switch (positionIndex) {
		case 0:
		case 1:
		case 2:
		case 3:
			(void) printf("cannot happen\n");
			return;
		case 4:
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 3, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			return;
		}
		break;
	case 1:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			return;
		}
		break;
	case 2:
		switch (positionIndex) {
		case 0:
		case 1:
		case 2:
			(void) printf("cannot happen\n");
			return;
		case 3:
			return;
		case 4:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			return;
		}
		break;
	case 3:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			return;
		}
		break;
	case 4:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			return;
		case 1:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			return;
		}
		break;
	case 5:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 2, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			return;
		}
		break;
	case 6:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			return;
		}
		break;
	}
}

static void
solve0LR4(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[0][0].face;
	int color1 = w->oct.facetLoc[6][0].face;
	int startFace = 0, startPositionIndex = 4;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 0LR4 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
		switch (positionIndex) {
		case 0:
		case 1:
		case 2:
		case 3:
			(void) printf("cannot happen\n");
			return;
		case 4:
			return;
		case 5:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			return;
		}
		break;
	case 1:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			return;
		}
		break;
	case 2:
		switch (positionIndex) {
		case 0:
		case 1:
		case 2:
		case 3:
			(void) printf("cannot happen\n");
			return;
		case 4:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			return;
		}
		break;
	case 3:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			return;
		}
		break;
	case 4:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			return;
		case 1:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			return;
		}
		break;
	case 5:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, startFace, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			return;
		}
		break;
	case 6:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			return;
		}
		break;
	}
}

static void
solve0LR5(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[0][0].face;
	int color1 = w->oct.facetLoc[6][0].face;
	int startFace = 0, startPositionIndex = 5;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 0LR5 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
		switch (positionIndex) {
		case 0:
		case 1:
		case 2:
		case 3:
		case 4:
			(void) printf("cannot happen\n");
			return;
		case 5:
			return;
		}
		break;
	case 1:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			return;
		}
		break;
	case 2:
		switch (positionIndex) {
		case 0:
		case 1:
		case 2:
		case 3:
			(void) printf("cannot happen\n");
			return;
		case 4:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			return;
		}
		break;
	case 3:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			return;
		}
		break;
	case 4:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			return;
		case 1:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			return;
		}
		break;
	case 5:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 6, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			return;
		}
		break;
	case 6:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			return;
		}
		break;
	}
}

static void
solve1LR5(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[1][0].face;
	int color1 = w->oct.facetLoc[5][0].face;
	int startFace = 1, startPositionIndex = 5;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 1LR5 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
		(void) printf("cannot happen\n");
		return;
	case 1:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			return;
		case 5:
			return;
		}
		break;
	case 2:
		switch (positionIndex) {
		case 0:
		case 1:
		case 2:
		case 3:
			(void) printf("cannot happen\n");
			return;
		case 4:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			return;
		}
		break;
	case 3:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 1),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 1),
				TL, PERIOD4, FALSE);
			return;
		}
		break;
	case 4:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				BR, PERIOD4, FALSE);
			return;
		case 1:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			return;
		}
		break;
	case 5:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			return;
		}
		break;
	case 6:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			return;
		}
		break;
	}
}

static void
solve3LR4(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[3][0].face;
	int color1 = w->oct.facetLoc[7][0].face;
	int startFace = 3, startPositionIndex = 4;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 3LR4 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
		(void) printf("cannot happen\n");
		return;
	case 1:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			return;
		case 5:
			(void) printf("cannot happen\n");
			return;
		}
		break;
	case 2:
		switch (positionIndex) {
		case 0:
		case 1:
		case 2:
		case 3:
			(void) printf("cannot happen\n");
			return;
		case 4:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			return;
		}
		break;
	case 3:
		switch (positionIndex) {
		case 4:
			return;
		case 5:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			return;
		}
		break;
	case 4:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 0),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 0),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			return;
		case 1:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			return;
		}
		break;
	case 5:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 0),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 0),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			return;
		}
		break;
	case 6:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 0),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 0),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			return;
		}
		break;
	}
}

static void
solve6LR2(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[6][0].face;
	int color1 = w->oct.facetLoc[5][0].face;
	int startFace = 6, startPositionIndex = 2;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 6LR2 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
		(void) printf("cannot happen\n");
		return;
	case 1:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			return;
		case 5:
			(void) printf("cannot happen\n");
			return;
		}
		break;
	case 2:
		switch (positionIndex) {
		case 0:
		case 1:
		case 2:
		case 3:
			(void) printf("cannot happen\n");
			return;
		case 4:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			return;
		}
		break;
	case 3:
		switch (positionIndex) {
		case 4:
			(void) printf("cannot happen\n");
			return;
		case 5:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			return;
		}
		break;
	case 4:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			return;
		case 1:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			return;
		}
		break;
	case 6:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			return;
		case 1:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			return;
		case 2:
			return;
		case 3:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			return;
		}
		break;
	}
}

static void
solve6LR3(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[6][0].face;
	int color1 = w->oct.facetLoc[7][0].face;
	int startFace = 6, startPositionIndex = 3;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 6LR3 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
		(void) printf("cannot happen\n");
		return;
	case 1:
		switch (positionIndex) {
		case 4:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			return;
		case 5:
			(void) printf("cannot happen\n");
			return;
		}
		break;
	case 2:
		switch (positionIndex) {
		case 0:
		case 1:
		case 2:
		case 3:
			(void) printf("cannot happen\n");
			return;
		case 4:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			return;
		}
		break;
	case 3:
		switch (positionIndex) {
		case 4:
			(void) printf("cannot happen\n");
			return;
		case 5:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			return;
		}
		break;
	case 4:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			return;
		case 1:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			return;
		}
		break;
	case 6:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			return;
		case 1:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			return;
		case 2:
			(void) printf("cannot happen\n");
			return;
		case 3:
			return;
		}
		break;
	}
}

static void
solve1LR4(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[1][0].face;
	int color1 = w->oct.facetLoc[5][0].face;
	int startFace = 1, startPositionIndex = 4;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 1LR4 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
		(void) printf("cannot happen\n");
		return;
	case 1:
		switch (positionIndex) {
		case 4:
			return;
		case 5:
			(void) printf("cannot happen\n");
			return;
		}
		break;
	case 2:
		switch (positionIndex) {
		case 0:
		case 1:
		case 2:
		case 3:
			(void) printf("cannot happen\n");
			return;
		case 4:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			return;
		}
		break;
	case 3:
		switch (positionIndex) {
		case 4:
			(void) printf("cannot happen\n");
			return;
		case 5:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			return;
		}
		break;
	case 4:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 0),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 0),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			return;
		case 1:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			return;
		}
		break;
	case 5:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			return;
		}
		break;
	case 6:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 0),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 0),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 5, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			return;
		case 2:
		case 3:
			(void) printf("cannot happen\n");
			return;
		}
		break;
	}
}

static void
solve3LR5(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[3][0].face;
	int color1 = w->oct.facetLoc[7][0].face;
	int startFace = 3, startPositionIndex = 5;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 3LR5 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
	case 1:
		(void) printf("cannot happen\n");
		return;
	case 2:
		switch (positionIndex) {
		case 0:
		case 1:
		case 2:
		case 3:
			(void) printf("cannot happen\n");
			return;
		case 4:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			return;
		}
		break;
	case 3:
		switch (positionIndex) {
		case 4:
			(void) printf("cannot happen\n");
			return;
		case 5:
			return;
		}
		break;
	case 4:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			return;
		case 1:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			return;
		}
		break;
	case 5:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 1),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 1),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			return;
		}
		break;
	case 6:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 7, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			return;
		case 2:
		case 3:
			(void) printf("cannot happen\n");
			return;
		}
		break;
	}
}

static void
solve6LR0(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[6][0].face;
	int color1 = w->oct.facetLoc[7][0].face;
	int startFace = 6, startPositionIndex = 0;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 6LR0 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
	case 1:
	case 3:
	case 5:
		(void) printf("cannot happen\n");
		return;
	case 2:
		switch (positionIndex) {
		case 0:
		case 1:
		case 2:
		case 3:
			(void) printf("cannot happen\n");
			return;
		case 4:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			return;
		}
		break;
	case 4:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			return;
		case 1:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			return;
		}
		break;
	case 6:
		switch (positionIndex) {
		case 0:
			return;
		case 1:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			return;
		case 2:
		case 3:
			(void) printf("cannot happen\n");
			return;
		}
		break;
	}
}

static void
solve6LR1(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[6][0].face;
	int color1 = w->oct.facetLoc[5][0].face;
	int startFace = 6, startPositionIndex = 1;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 6LR1 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
	case 1:
	case 3:
	case 5:
		(void) printf("cannot happen\n");
		return;
	case 2:
		switch (positionIndex) {
		case 0:
		case 1:
		case 2:
		case 3:
			(void) printf("cannot happen\n");
			return;
		case 4:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, 4, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			return;
		}
		break;
	case 4:
		switch (positionIndex) {
		case 0:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			return;
		case 1:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			return;
		}
		break;
	case 6:
		switch (positionIndex) {
		case 0:
		case 2:
		case 3:
			(void) printf("cannot happen\n");
			return;
		case 1:
			return;
		}
		break;
	}
}

static void
solve4LR0(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[4][0].face;
	int color1 = w->oct.facetLoc[5][0].face;
	int startFace = 4, startPositionIndex = 0;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 4LR0 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
	case 1:
	case 2:
	case 3:
	case 5:
	case 6:
		(void) printf("cannot happen\n");
		return;
	case 4:
		switch (positionIndex) {
		case 0:
			return;
		case 1:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			return;
		case 2:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			return;
		case 4:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			return;
		}
		break;
	}
}

static void
solve4LR1(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[4][0].face;
	int color1 = w->oct.facetLoc[7][0].face;
	int startFace = 4, startPositionIndex = 1;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 4LR1 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
	case 1:
	case 2:
	case 3:
	case 5:
	case 6:
		(void) printf("cannot happen\n");
		return;
	case 4:
		switch (positionIndex) {
		case 0:
			(void) printf("cannot happen\n");
			return;
		case 1:
			return;
		case 2:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BR, PERIOD4, FALSE);
			return;
		case 4:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				TL, PERIOD4, FALSE);
			return;
		case 5:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 4),
				BL, PERIOD4, FALSE);
			return;
		}
		break;
	}
}

static void
solve4LR5(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[4][0].face;
	int color1 = w->oct.facetLoc[2][0].face;
	int startFace = 4, startPositionIndex = 5;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 4LR5 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
	case 1:
	case 2:
	case 3:
	case 5:
	case 6:
		(void) printf("cannot happen\n");
		return;
	case 4:
		switch (positionIndex) {
		case 0:
		case 1:
			(void) printf("cannot happen\n");
			return;
		case 2:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 2),
				CW, PERIOD4, FALSE);
			return;
		case 4:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				TR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 5),
				BL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 0),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 1),
				TR, PERIOD4, FALSE);
			return;
		case 5:
			return;
		}
		break;
	}
}

static void
solve4LR4(OctWidget w)
{
	int face, position, positionIndex;
	int color0 = w->oct.facetLoc[4][0].face;
	int color1 = w->oct.facetLoc[2][0].face;
	int startFace = 4, startPositionIndex = 4;

	face = startFace;
	position = indexToEdgeLR(w, startPositionIndex);
	findPieceLR(w, color0, color1, &face, &position);
	positionIndex = edgeLRToIndex(w, position);
#ifdef DEBUG
	(void) printf("findPieceLR 4LR4 color0=%d color1=%d : face=%d positionIndex=%d\n",
		color0, color1, face, positionIndex);
#endif
	switch (face) {
	case 0:
	case 1:
	case 2:
	case 3:
	case 5:
	case 6:
		(void) printf("cannot happen\n");
		return;
	case 4:
		switch (positionIndex) {
		case 0:
		case 1:
		case 5:
			(void) printf("cannot happen\n");
			return;
		case 2:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			return;
		case 3:
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				BR, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				CCW, PERIOD4, FALSE);
			movePuzzlePiece(w, face, indexToEdgeLR(w, 3),
				TL, PERIOD4, FALSE);
			return;
		case 4:
			return;
		}
		break;
	}
}

static void
solveFace0(OctWidget w)
{
	solve0LR0(w);
	solve0LR1(w);
	solve0LR2(w);
	solve0LR3(w);
}

static void
solveFace2(OctWidget w)
{
	solve2LR0(w);
	solve2LR1(w);
	solve2LR2(w);
	solve2LR3(w);
}

static void
solveUpperEdge(OctWidget w)
{
	solve0LR4(w);
	solve0LR5(w);
	solve1LR5(w);
	solve3LR4(w);
	solve6LR2(w);
	solve6LR3(w);
}

static void
solveLowerEdge(OctWidget w)
{
	solve1LR4(w);
	solve3LR5(w);
	solve6LR0(w);
	solve6LR1(w);
}

static void
solveLastEdges(OctWidget w)
{
	solve4LR0(w);
	solve4LR1(w);
	solve4LR5(w);
	solve4LR4(w);
}

static int
exactCenter(OctWidget w)
{
	int size = w->oct.size;
	int i;

	if (size % 3 == 0)
		size--; /* no exact center here */
	if ((size + 2) % 3 == 0) {
		i = ((size - 1) / 3) * 2;
		return i * i + i;
	} else /*if ((size + 1) % 3 == 0)*/ {
		i = ((size - 2) / 3) * 2 + 1;
		return i * i + i;
	}
}

static int
findPieceCenter(OctWidget w, int color0, int startFace)
{
	int face;
	int position = exactCenter(w);

	/* Check starting face first */
	if (w->oct.facetLoc[startFace][position].face == color0) {
#ifdef DEBUG
		(void) printf("Center %d %d\n", startFace, position);
#endif
		return startFace;
	}
	for (face = 0; face < MAX_FACES; face++) {
		if (face == startFace)
			continue;
		if (w->oct.facetLoc[face][position].face == color0) {
#ifdef DEBUG
			(void) printf("Center fs %d %d\n", face, position);
#endif
			return face;
		}
	}
	(void) printf("Piece %d not found!\n", color0);
	return -1;
}

static int oppDir(int dir) {
	switch (dir) {
		case TOP: return BOTTOM;
		case TR: return BL;
		case RIGHT: return LEFT;
		case BR: return TL;
		case BOTTOM: return TOP;
		case BL: return TR;
		case LEFT: return RIGHT;
		case TL: return BR;
		case CW: return CCW;
		case CCW: return CW;
		default:
			(void) printf("no default %d\n", dir);
			return -1;
	}
}

static void simpleCenterMove(OctWidget w, int face, int dir0, int dir1)
{
	int position = exactCenter(w);
	int i;

	for (i = 0; i < 3; i++) {
		movePuzzlePiece(w, face, position,
			dir0, PERIOD4, False);
		movePuzzlePiece(w, face, position,
			dir1, PERIOD4, False);
		movePuzzlePiece(w, face, position,
			oppDir(dir0), PERIOD4, False);
		movePuzzlePiece(w, face, position,
			oppDir(dir1), PERIOD4, False);
	}
}

static void
solveFace0Center(OctWidget w)
{
	int startFace = 0;
	int color0 = w->oct.facetLoc[startFace][0].face;
	int face = findPieceCenter(w, color0, startFace);
	int position = exactCenter(w);

	switch (face) {
	case 0:
			return;
		case 1:
			simpleCenterMove(w, startFace, CCW, TL);
			return;
		case 2:
			simpleCenterMove(w, 1, TR, BR);
			return;
		case 3:
			simpleCenterMove(w, startFace, CW, TR);
			return;
		case 4:
			movePuzzlePiece(w, face, position,
				TR, PERIOD4, False);
			simpleCenterMove(w, 1, TR, BR);
			movePuzzlePiece(w, face, position,
				BL, PERIOD4, False);
			return;
		case 5:
			simpleCenterMove(w, 1, CW, BL);
			return;
		case 6:
			simpleCenterMove(w, startFace, BR, BL);
			return;
		case 7:
			simpleCenterMove(w, 3, CCW, BR);
			return;
		default:
			(void) printf("not done yet %d\n", face);
			return;
	}
}

static void
solveFace1Center(OctWidget w)
{
	int startFace = 1;
	int color0 = w->oct.facetLoc[startFace][0].face;
	int face = findPieceCenter(w, color0, startFace);
	int position = exactCenter(w);

	switch (face) {
		case 0:
			(void) printf("should not happen %d\n", face);
			return;
		case 1:
			return;
		case 2:
			simpleCenterMove(w, face, CCW, TR);
			return;
		case 3:
			simpleCenterMove(w, 2, BL, BR);
			return;
		case 4:
			simpleCenterMove(w, 2, CW, TL);
			return;
		case 5:
			simpleCenterMove(w, face, TR, BR);
			return;
		case 6:
			simpleCenterMove(w, 4, CCW, TL);
			return;
		case 7:
			movePuzzlePiece(w, face, position,
				TL, PERIOD4, False);
			simpleCenterMove(w, 2, BR, BL);
			movePuzzlePiece(w, face, position,
				BR, PERIOD4, False);
			return;
		default:
			(void) printf("not done yet %d\n", face);
			return;
	}
}

static void
solveFace3Center(OctWidget w)
{
	int startFace = 3;
	int color0 = w->oct.facetLoc[startFace][0].face;
	int face = findPieceCenter(w, color0, startFace);
	int position = exactCenter(w);

	switch (face) {
		case 0:
		case 1:
			(void) printf("should not happen %d\n", face);
			return;
		case 2:
			movePuzzlePiece(w, face, position,
				TR, PERIOD4, False);
			simpleCenterMove(w, face, BR, BL);
			movePuzzlePiece(w, face, position,
				BL, PERIOD4, False);
			return;
		case 3:
			return;
		case 4:
			simpleCenterMove(w, 6, CCW, BR);
			return;
		case 5:
			movePuzzlePiece(w, face, position,
				BL, PERIOD4, False);
			simpleCenterMove(w, 4, CW, TR);
			movePuzzlePiece(w, face, position,
				TR, PERIOD4, False);
			return;
		case 6:
			simpleCenterMove(w, 4, CW, TR);
			return;
		case 7:
			simpleCenterMove(w, face, TL, BL);
			return;
		default:
			(void) printf("not done yet %d\n", face);
			return;
	}
}

static void
solveFace6Center(OctWidget w)
{
	int startFace = 6;
	int color0 = w->oct.facetLoc[startFace][0].face;
	int face = findPieceCenter(w, color0, startFace);
	int position = exactCenter(w);

	switch (face) {
		case 0:
		case 1:
		case 3:
			(void) printf("should not happen %d\n", face);
			return;
		case 2:
			movePuzzlePiece(w, face, position,
				CW, PERIOD4, False);
			movePuzzlePiece(w, face, position,
				CW, PERIOD4, False);
			simpleCenterMove(w, startFace, BR, BL);
			movePuzzlePiece(w, face, position,
				CW, PERIOD4, False);
			movePuzzlePiece(w, face, position,
				CW, PERIOD4, False);
			return;
		case 4:
			movePuzzlePiece(w, face, position,
				TL, PERIOD4, False);
			movePuzzlePiece(w, 2, position,
				CW, PERIOD4, False);
			simpleCenterMove(w, face, CW, TR);
			movePuzzlePiece(w, 2, position,
				CCW, PERIOD4, False);
			movePuzzlePiece(w, face, position,
				BR, PERIOD4, False);
			return;
		case 5:
			movePuzzlePiece(w, 2, position,
				CW, PERIOD4, False);
			movePuzzlePiece(w, face, position,
				TL, PERIOD4, False);
			simpleCenterMove(w, 7, TL, BL);
			movePuzzlePiece(w, face, position,
				BR, PERIOD4, False);
			movePuzzlePiece(w, 2, position,
				CCW, PERIOD4, False);
			return;
		case 6:
			return;
		case 7:
			movePuzzlePiece(w, 2, position,
				CCW, PERIOD4, False);
			movePuzzlePiece(w, face, position,
				TR, PERIOD4, False);
			simpleCenterMove(w, 5, TR, BR);
			movePuzzlePiece(w, face, position,
				BL, PERIOD4, False);
			movePuzzlePiece(w, 2, position,
				CW, PERIOD4, False);
			return;
		default:
			(void) printf("not done yet %d\n", face);
			return;
	}
}

static void
lastCenters(OctWidget w)
{
	int bgColors[MAX_FACES], centerColors[MAX_FACES];
	int lastColors[4] = {2, 4, 5, 7};
	int colorSequence[4];
	int position = exactCenter(w);
	int i, j;

	for (i = 0; i < 4; i++) {
		int lastColor = lastColors[i];
		bgColors[lastColor] =
			w->oct.facetLoc[lastColor][0].face;
		centerColors[lastColor] =
			w->oct.facetLoc[lastColor][position].face;
		colorSequence[i] = -1;
	}
	for (i = 0; i < 4; i++) {
		int bgColor = bgColors[lastColors[i]];
		for (j = 0; j < 4; j++) {
			if (bgColor == centerColors[lastColors[j]]) {
				colorSequence[i] = j;
			}
		}
	}
	/* 12 possibilities */
	if (colorSequence[0] == 0 && colorSequence[1] == 1 &&
			colorSequence[2] == 2 && colorSequence[3] == 3) {
		return;
	} else if (colorSequence[0] == 0 && colorSequence[1] == 2 &&
			colorSequence[2] == 3 && colorSequence[3] == 1) {
		/* 0231 */
		movePuzzlePiece(w, 5, position,
			BL, PERIOD4, False);
		simpleCenterMove(w, 4, CCW, BL);
		movePuzzlePiece(w, 5, position,
			TR, PERIOD4, False);
		movePuzzlePiece(w, 4, position,
			BL, PERIOD4, False);
		movePuzzlePiece(w, 2, position,
			CW, PERIOD4, False);
		simpleCenterMove(w, 4, TR, TL);
		movePuzzlePiece(w, 2, position,
			CCW, PERIOD4, False);
		movePuzzlePiece(w, 4, position,
			TR, PERIOD4, False);
	} else if (colorSequence[0] == 0 && colorSequence[1] == 3 &&
			colorSequence[2] == 1 && colorSequence[3] == 2) {
		/* 0312 */
		movePuzzlePiece(w, 7, position,
			BR, PERIOD4, False);
		simpleCenterMove(w, 4, CW, BR);
		movePuzzlePiece(w, 7, position,
			TL, PERIOD4, False);
		movePuzzlePiece(w, 4, position,
			BR, PERIOD4, False);
		movePuzzlePiece(w, 2, position,
			CCW, PERIOD4, False);
		simpleCenterMove(w, 4, TR, TL);
		movePuzzlePiece(w, 2, position,
			CW, PERIOD4, False);
		movePuzzlePiece(w, 4, position,
			TL, PERIOD4, False);
	} else if (colorSequence[0] == 1 && colorSequence[1] == 0 &&
			colorSequence[2] == 3 && colorSequence[3] == 2) {
		/* 1032 */
		simpleCenterMove(w, 4, TR, TL);
	} else if (colorSequence[0] == 1 && colorSequence[1] == 2 &&
			colorSequence[2] == 0 && colorSequence[3] == 3) {
		/* 1203 */
		movePuzzlePiece(w, 5, position,
			BL, PERIOD4, False);
		simpleCenterMove(w, 4, TR, TL);
		movePuzzlePiece(w, 5, position,
			TR, PERIOD4, False);
		movePuzzlePiece(w, 2, position,
			CW, PERIOD4, False);
		simpleCenterMove(w, 4, CW, BR);
		movePuzzlePiece(w, 2, position,
			CCW, PERIOD4, False);
	} else if (colorSequence[0] == 1 && colorSequence[1] == 3 &&
			colorSequence[2] == 2 && colorSequence[3] == 0) {
		/* 1320 */
		movePuzzlePiece(w, 6, position,
			BR, PERIOD4, False);
		simpleCenterMove(w, 4, TR, TL);
		movePuzzlePiece(w, 6, position,
			TL, PERIOD4, False);
		movePuzzlePiece(w, 2, position,
			CCW, PERIOD4, False);
		simpleCenterMove(w, 4, CCW, BL);
		movePuzzlePiece(w, 2, position,
			CW, PERIOD4, False);
	} else if (colorSequence[0] == 2 && colorSequence[1] == 0 &&
			colorSequence[2] == 1 && colorSequence[3] == 3) {
		/* 2013 */
		movePuzzlePiece(w, 4, position,
			TR, PERIOD4, False);
		simpleCenterMove(w, 4, CCW, BL);
		movePuzzlePiece(w, 4, position,
			BL, PERIOD4, False);
		movePuzzlePiece(w, 4, position,
			BR, PERIOD4, False);
		movePuzzlePiece(w, 2, position,
			CCW, PERIOD4, False);
		simpleCenterMove(w, 4, CW, BR);
		movePuzzlePiece(w, 2, position,
			CW, PERIOD4, False);
		movePuzzlePiece(w, 4, position,
			TL, PERIOD4, False);
	} else if (colorSequence[0] == 2 && colorSequence[1] == 1 &&
			colorSequence[2] == 3 && colorSequence[3] == 0) {
		/* 2130 */
		movePuzzlePiece(w, 6, position,
			BR, PERIOD4, False);
		simpleCenterMove(w, 4, CCW, BL);
		movePuzzlePiece(w, 6, position,
			TL, PERIOD4, False);
		movePuzzlePiece(w, 2, position,
			CCW, PERIOD4, False);
		simpleCenterMove(w, 4, TR, TL);
		movePuzzlePiece(w, 2, position,
			CW, PERIOD4, False);
	} else if (colorSequence[0] == 2 && colorSequence[1] == 3 &&
			colorSequence[2] == 0 && colorSequence[3] == 1) {
		/* 2301 */
		simpleCenterMove(w, 4, CCW, BL);
	} else if (colorSequence[0] == 3 && colorSequence[1] == 0 &&
			colorSequence[2] == 2 && colorSequence[3] == 1) {
		/* 3021 */
		movePuzzlePiece(w, 4, position,
			TR, PERIOD4, False);
		simpleCenterMove(w, 4, TR, TL);
		movePuzzlePiece(w, 4, position,
			BL, PERIOD4, False);
		movePuzzlePiece(w, 4, position,
			BL, PERIOD4, False);
		simpleCenterMove(w, 4, CCW, BL);
		movePuzzlePiece(w, 4, position,
			TR, PERIOD4, False);
	} else if (colorSequence[0] == 3 && colorSequence[1] == 1 &&
			colorSequence[2] == 0 && colorSequence[3] == 2) {
		/* 3102 */
		movePuzzlePiece(w, 5, position,
			BL, PERIOD4, False);
		simpleCenterMove(w, 4, CW, BR);
		movePuzzlePiece(w, 5, position,
			TR, PERIOD4, False);
		movePuzzlePiece(w, 2, position,
			CW, PERIOD4, False);
		simpleCenterMove(w, 4, TR, TL);
		movePuzzlePiece(w, 2, position,
			CCW, PERIOD4, False);
	} else if (colorSequence[0] == 3 && colorSequence[1] == 2 &&
			colorSequence[2] == 1 && colorSequence[3] == 0) {
		/* 3210 */
		simpleCenterMove(w, 4, CW, BR);
	} else {
		/* seems like more possibilities when size 5 */
		(void) printf("%d%d%d%d center not done\n",
			colorSequence[0], colorSequence[1],
			colorSequence[2], colorSequence[3]);
	}
}


static void
centerRotate123(OctWidget w, int face, int dir0, int dir1, int dir2) {
	int i;
	int position = exactCenter(w);

	for (i = 0; i < 28; i++) {
		movePuzzlePiece(w, face, position,
			dir0, PERIOD4, False);
		movePuzzlePiece(w, face, position,
			dir1, PERIOD4, False);
		movePuzzlePiece(w, face, position,
			dir2, PERIOD4, False);
	}
}

static void
centerRotate4(OctWidget w, int dir) {
	switch (dir) {
	case TR:
		centerRotate123(w, 4, CW, BL, TL); /* / CW */
		return;
	case BL:
		centerRotate123(w, 4, BR, TR, CCW); /* / CCW */
		return;
	case BR:
		centerRotate123(w, 4, BL, TL, CW); /* \ CW */
		return;
	case TL:
		centerRotate123(w, 4, CCW, BR, TR); /* \ CCW */
		return;
	case RIGHT:
		centerRotate123(w, 4, TL, CW, BL); /* - CW */
		return;
	case LEFT:
		centerRotate123(w, 4, TR, CCW, BR); /* - CCW */
		return;
	default:
		break;
	}
}

static int
findPieceCenterOrient(OctWidget w, int face)
{
	int position = exactCenter(w);

	return (w->oct.facetLoc[face][position].rotation + MAX_ORIENT -
		w->oct.facetLoc[face][0].rotation) % 3;
}

#if 0
static void
checkOrient(OctWidget w)
{
	int i, value;
	for (i = 0; i < 8; i++) {
		value = findPieceCenterOrient(w, i);
		(void) printf("%d: %d\n", i, value);
	}
}
#endif

static void
rotateFirstHalf(OctWidget w) {
	int face = 0;
	int value = findPieceCenterOrient(w, face);

	if (value != 0) {
		Boolean opp = (value == 1);
#ifdef DEBUG
		(void) printf("%d %d\n", face, value);
#endif
		if (opp) {
			centerRotate123(w, face, TR, CCW, BR);
		} else {
			centerRotate123(w, face, TL, CW, BL);
		}
	}
	face = 3;
	value = findPieceCenterOrient(w, face);
	if (value != 0) {
		Boolean opp = (value == 1);
#ifdef DEBUG
		(void) printf("%d %d\n", face, value);
#endif
		if (opp) {
			centerRotate123(w, 2, CCW, TL, BL);
		} else {
			centerRotate123(w, 2, TR, BR, CW);
		}
	}
	face = 1;
	value = findPieceCenterOrient(w, face);
	if (value != 0) {
		Boolean opp = (value == 1);
#ifdef DEBUG
		(void) printf("%d %d\n", face, value);
#endif
		if (opp) {
			centerRotate123(w, 2, TL, BL, CCW);
		} else {
			centerRotate123(w, 2, CW, TR, BR);
		}
	}
	face = 6;
	value = findPieceCenterOrient(w, face);
	if (value != 0) {
		Boolean opp = (value == 1);
#ifdef DEBUG
		(void) printf("%d %d\n", face, value);
#endif
		if (opp) {
			centerRotate123(w, face, BL, CCW, TL);
		} else {
			centerRotate123(w, face, BR, CW, TR);
		}
	}
}

static void
rotateLastHalf(OctWidget w) {
	int lastOrients[4] = {2, 4, 5, 7};
	int orientSequence[4];
	int i;

	for (i = 0; i < 4; i++)
		orientSequence[i] = findPieceCenterOrient(w, lastOrients[i]);
#ifdef DEBUG
	(void) printf("last half %d%d%d%d\n",
		orientSequence[1], orientSequence[0],
		orientSequence[2], orientSequence[3]);
#endif
	if (orientSequence[1] == 0 && orientSequence[0] == 0 &&
			orientSequence[2] == 0 && orientSequence[3] == 0) {
		return;
	} else if (orientSequence[1] == 0 && orientSequence[0] == 0 &&
			orientSequence[2] == 1 && orientSequence[3] == 2) {
		/* 0012 1122 2202 */
		centerRotate4(w, BR);
		centerRotate4(w, BR);
		centerRotate4(w, TR);
	} else if (orientSequence[1] == 0 && orientSequence[0] == 0 &&
			orientSequence[2] == 2 && orientSequence[3] == 1) {
		/* 0021 1122 2220 */
		centerRotate4(w, TR);
		centerRotate4(w, TR);
		centerRotate4(w, BR);
	} else if (orientSequence[1] == 0 && orientSequence[0] == 1 &&
			orientSequence[2] == 0 && orientSequence[3] == 2) {
		/* 0102 1212 2022 */
		centerRotate4(w, BR);
		centerRotate4(w, BR);
		centerRotate4(w, RIGHT);
	} else if (orientSequence[1] == 0 && orientSequence[0] == 1 &&
			orientSequence[2] == 1 && orientSequence[3] == 1) {
		/* 0111 1221 2022 */
		centerRotate4(w, BR);
		centerRotate4(w, TR);
		centerRotate4(w, RIGHT);
	} else if (orientSequence[1] == 0 && orientSequence[0] == 1 &&
			orientSequence[2] == 2 && orientSequence[3] == 0) {
		/* 0120 1221 2022 */
		centerRotate4(w, TR);
		centerRotate4(w, TR);
		centerRotate4(w, RIGHT);
	} else if (orientSequence[1] == 0 && orientSequence[0] == 2 &&
			orientSequence[2] == 0 && orientSequence[3] == 1) {
		/* 0201 1212 2022 */
		centerRotate4(w, RIGHT);
		centerRotate4(w, BR);
		centerRotate4(w, RIGHT);
	} else if (orientSequence[1] == 0 && orientSequence[0] == 2 &&
			orientSequence[2] == 1 && orientSequence[3] == 0) {
		/* 0210 1212 2022 */
		centerRotate4(w, RIGHT);
		centerRotate4(w, TR);
		centerRotate4(w, RIGHT);
	} else if (orientSequence[1] == 0 && orientSequence[0] == 2 &&
			orientSequence[2] == 2 && orientSequence[3] == 2) {
		/* 0222 2112 1011 */
		centerRotate4(w, TL);
		centerRotate4(w, BL);
		centerRotate4(w, LEFT);
	} else if (orientSequence[1] == 1 && orientSequence[0] == 0 &&
			orientSequence[2] == 0 && orientSequence[3] == 2) {
		/* 1002 2112 1011 */
		centerRotate4(w, BR);
		centerRotate4(w, BL);
		centerRotate4(w, LEFT);
	} else if (orientSequence[1] == 1 && orientSequence[0] == 0 &&
			orientSequence[2] == 1 && orientSequence[3] == 1) {
		/* 1011 */
		centerRotate4(w, LEFT);
	} else if (orientSequence[1] == 1 && orientSequence[0] == 0 &&
			orientSequence[2] == 2 && orientSequence[3] == 0) {
		/* 1020 2121 1011 */
		centerRotate4(w, TR);
		centerRotate4(w, TL);
		centerRotate4(w, LEFT);
	} else if (orientSequence[1] == 1 && orientSequence[0] == 1 &&
			orientSequence[2] == 0 && orientSequence[3] == 1) {
		/* 1101 */
		centerRotate4(w, BL);
	} else if (orientSequence[1] == 1 && orientSequence[0] == 1 &&
			orientSequence[2] == 1 && orientSequence[3] == 0) {
		/* 1110 */
		centerRotate4(w, TL);
	} else if (orientSequence[1] == 1 && orientSequence[0] == 1 &&
			orientSequence[2] == 2 && orientSequence[3] == 2) {
		/* 1122 2220 */
		centerRotate4(w, TR);
		centerRotate4(w, BR);
	} else if (orientSequence[1] == 1 && orientSequence[0] == 2 &&
			orientSequence[2] == 0 && orientSequence[3] == 0) {
		/* 1200 2211 1110 */
		centerRotate4(w, RIGHT);
		centerRotate4(w, BL);
		centerRotate4(w, TL);
	} else if (orientSequence[1] == 1 && orientSequence[0] == 2 &&
			orientSequence[2] == 1 && orientSequence[3] == 2) {
		/* 1212 2022 */
		centerRotate4(w, BR);
		centerRotate4(w, RIGHT);
	} else if (orientSequence[1] == 1 && orientSequence[0] == 2 &&
			orientSequence[2] == 2 && orientSequence[3] == 1) {
		/* 1221 2022 */
		centerRotate4(w, TR);
		centerRotate4(w, RIGHT);
	} else if (orientSequence[1] == 2 && orientSequence[0] == 0 &&
			orientSequence[2] == 0 && orientSequence[3] == 1) {
		/* 2001 1221 2022 */
		centerRotate4(w, TL);
		centerRotate4(w, TR);
		centerRotate4(w, RIGHT);
	} else if (orientSequence[1] == 2 && orientSequence[0] == 0 &&
			orientSequence[2] == 1 && orientSequence[3] == 0) {
		/* 2010 1212 2022 */
		centerRotate4(w, BL);
		centerRotate4(w, BR);
		centerRotate4(w, RIGHT);
	} else if (orientSequence[1] == 2 && orientSequence[0] == 0 &&
			orientSequence[2] == 2 && orientSequence[3] == 2) {
		/* 2022 */
		centerRotate4(w, RIGHT);
	} else if (orientSequence[1] == 2 && orientSequence[0] == 1 &&
			orientSequence[2] == 0 && orientSequence[3] == 0) {
		/* 2100 1122 2220 */
		centerRotate4(w, LEFT);
		centerRotate4(w, TR);
		centerRotate4(w, BR);
	} else if (orientSequence[1] == 2 && orientSequence[0] == 1 &&
			orientSequence[2] == 1 && orientSequence[3] == 2) {
		/* 2112 1011 */
		centerRotate4(w, BL);
		centerRotate4(w, LEFT);
	} else if (orientSequence[1] == 2 && orientSequence[0] == 1 &&
			orientSequence[2] == 2 && orientSequence[3] == 1) {
		/* 2121 1011 */
		centerRotate4(w, TL);
		centerRotate4(w, LEFT);
	} else if (orientSequence[1] == 2 && orientSequence[0] == 2 &&
			orientSequence[2] == 0 && orientSequence[3] == 2) {
		/* 2202 */
		centerRotate4(w, TR);
	} else if (orientSequence[1] == 2 && orientSequence[0] == 2 &&
			orientSequence[2] == 1 && orientSequence[3] == 1) {
		/* 2211 1110 */
		centerRotate4(w, BL);
		centerRotate4(w, TL);
	} else if (orientSequence[1] == 2 && orientSequence[0] == 2 &&
			orientSequence[2] == 2 && orientSequence[3] == 0) {
		/* 2220 */
		centerRotate4(w, BR);
	}
#ifdef DEBUG
	for (i = 0; i < 4; i++)
		orientSequence[i] = findPieceCenterOrient(w, lastOrients[i]);
	(void) printf("final %d%d%d%d\n",
		orientSequence[1], orientSequence[0],
		orientSequence[2], orientSequence[3]);
#endif
}

static void
solveCorners(OctWidget w)
{
	if (w->oct.size > 2) {
		solveTopFace(w);
		solveSecondFace(w);
		solveThirdCorner(w);
		lastCount = 0;
		solveLastCorner(w);
		if (w->oct.size > 3) {
			solveFace0(w);
			solveFace2(w);
			solveUpperEdge(w);
			solveLowerEdge(w);
			solveLastEdges(w);
			if (w->oct.size % 3 != 0) {
				solveFace0Center(w);
				solveFace1Center(w);
				solveFace3Center(w);
				solveFace6Center(w);
				lastCenters(w);
				if (w->oct.orient) {
					rotateFirstHalf(w);
					rotateLastHalf(w);
				}
			}
		}
	} else {
		allTrivialCorners(w);
	}
}

static Boolean
checkCornerPiece(OctWidget w, int color, int face, int position)
{
	int newFace, newPosition, positionIndex;

	positionIndex = cornerToIndex(w, position);
	if (positionIndex == -1) {
		positionIndex = 0;
		(void) printf("position %d incorrect\n", position);
	}
	newFace = edgeMateCorner[face][positionIndex];
	newPosition = indexToCornerMate(w, positionIndex);
	return (w->oct.facetLoc[newFace][newPosition].face == color);
}

static void
findCornerPiece(OctWidget w, int color0, int color1, int *face, int *position)
{
	int positionIndex;

	for (*face = 0; *face < MAX_FACES; (*face)++) {
		for (positionIndex = 0; positionIndex < 3; positionIndex++) {
			*position = indexToCorner(w, positionIndex);
			if (w->oct.facetLoc[*face][*position].face == color0 &&
					checkCornerPiece(w, color1, *face, *position)) {
				return;
			}
		}
	}
	(void) printf("Corner piece %d %d not found!\n", color0, color1);
}

static void
solveTrCorner(OctWidget w)
{
	/* Pick a face (0) and determine which color is present at each
	 * corner. */
	int topColor = w->oct.facetLoc[0][0].face;
	int otherColor = w->oct.facetLoc[1][0].face;
	int face, position;
	findCornerPiece(w, topColor, otherColor, &face, &position);
#ifdef DEBUG
	(void) printf("TR face %d, position %d\n", face, position);
#endif
	if (face == 0 && position == indexToCorner(w, 1))
		return;
	else if (face == 0 && position == indexToCorner(w, 2)) {
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
	} else if (face == 2 && position == indexToCorner(w, 2)) {
		movePuzzlePiece(w, 1, indexToCorner(w, 2),
			TOP, PERIOD3, False);
	} else if (face == 2 && position == indexToCorner(w, 1)) {
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
	} else if (face == 5 && position == indexToCorner(w, 0)) {
		movePuzzlePiece(w, 0, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
	} else if (face == 5 && position == indexToCorner(w, 2)) {
		movePuzzlePiece(w, 1, indexToCorner(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
	} else if (face == 5 && position == indexToCorner(w, 1)) {
		movePuzzlePiece(w, 1, indexToCorner(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
	} else if (face == 7 && position == indexToCorner(w, 0)) {
		movePuzzlePiece(w, 1, indexToCorner(w, 2),
			BOTTOM, PERIOD3, False);
	} else if (face == 7 && position == indexToCorner(w, 2)) {
		movePuzzlePiece(w, 0, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
	} else if (face == 7 && position == indexToCorner(w, 1)) {
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToCorner(w, 2),
			BOTTOM, PERIOD3, False);
	}
}

static void
solveTlCorner(OctWidget w)
{
	int topColor = w->oct.facetLoc[0][0].face;
	int otherColor = w->oct.facetLoc[3][0].face;
	int face, position;
	findCornerPiece(w, otherColor, topColor, &face, &position);
#ifdef DEBUG
	(void) printf("TL face %d, position %d\n", face, position);
#endif
	if (face == 1 && position == indexToCorner(w, 1)) {
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			BOTTOM, PERIOD3, False);
	} else if (face == 3 && position == indexToCorner(w, 2)) {
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			BOTTOM, PERIOD3, False);
	} else if (face == 3 && position == indexToCorner(w, 1)) {
		return;
	} else if (face == 4 && position == indexToCorner(w, 0)) {
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			TOP, PERIOD3, False);
	} else if (face == 4 && position == indexToCorner(w, 2)) {
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			TOP, PERIOD3, False);
	} else if (face == 4 && position == indexToCorner(w, 1)) {
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			TOP, PERIOD3, False);
	} else if (face == 6 && position == indexToCorner(w, 0)) {
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			BOTTOM, PERIOD3, False);
	} else if (face == 6 && position == indexToCorner(w, 1)) {
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			TOP, PERIOD3, False);
	}
}
static void
solveTopCorners(OctWidget w)
{
	solveTrCorner(w);
	solveTlCorner(w);
}

static void rotateLeftRightCorners (OctWidget w) {
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToCorner(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToCorner(w, 2),
			TOP, PERIOD3, False);
}

static int lastColor(OctWidget w)
{
	int faces[8];
	int i, j;

	faces[0] = w->oct.facetLoc[0][indexToCorner(w, 0)].face;
	faces[1] = w->oct.facetLoc[1][indexToCorner(w, 0)].face;
	faces[2] = w->oct.facetLoc[2][indexToCorner(w, 0)].face;
	faces[3] = w->oct.facetLoc[3][indexToCorner(w, 0)].face;
	faces[4] = w->oct.facetLoc[5][indexToCorner(w, 1)].face;
	faces[5] = w->oct.facetLoc[6][indexToCorner(w, 2)].face;
	faces[6] = w->oct.facetLoc[7][indexToCorner(w, 2)].face;
	faces[7] = -1;
	for (i = 0; i < 8; i++) {
		for (j = 0; j < 7; j++) {
			if (i == faces[j])
				break;
		}
		if (i != faces[j])
			return i;
	}
	return -1;
}

static void
solveBottomCorners(OctWidget w)
{
	int bottomColor = lastColor(w);
	int rightColor = w->oct.facetLoc[5][indexToCorner(w, 1)].face;
	int leftColor = w->oct.facetLoc[7][indexToCorner(w, 2)].face;
	int face[3], position[3];

	findCornerPiece(w, bottomColor, leftColor, &(face[0]), &(position[0]));
#ifdef DEBUG
	(void) printf("BOTTOM face %d, position %d\n", face[0], position[0]);
#endif
	findCornerPiece(w, bottomColor, rightColor, &(face[1]), &(position[1]));
#ifdef DEBUG
	(void) printf("RIGHT face %d, position %d\n", face[1], position[1]);
#endif
	findCornerPiece(w, leftColor, bottomColor, &(face[2]), &(position[2]));
#ifdef DEBUG
	(void) printf("LEFT face %d, position %d\n", face[2], position[2]);
#endif
	if (face[0] == 1 && position[0] == indexToCorner(w, 1) &&
			face[1] == 3 && position[1] == indexToCorner(w, 2) &&
			face[2] == 5 && position[2] == indexToCorner(w, 0)) {
		rotateLeftRightCorners(w);
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
	} else if (face[0] == 1 && position[0] == indexToCorner(w, 1) &&
			face[1] == 4 && position[1] == indexToCorner(w, 2) &&
			face[2] == 7 && position[2] == indexToCorner(w, 0)) {
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
		rotateLeftRightCorners(w);
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
	} else if (face[0] == 3 && position[0] == indexToCorner(w, 2) &&
			face[1] == 4 && position[1] == indexToCorner(w, 0) &&
			face[2] == 5 && position[2] == indexToCorner(w, 2)) {
		rotateLeftRightCorners(w);
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
	} else if (face[0] == 3 && position[0] == indexToCorner(w, 2) &&
			face[1] == 6 && position[1] == indexToCorner(w, 0) &&
			face[2] == 2 && position[2] == indexToCorner(w, 2)) {
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
		rotateLeftRightCorners(w);
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
	} else if (face[0] == 4 && position[0] == indexToCorner(w, 0) &&
			face[1] == 1 && position[1] == indexToCorner(w, 1) &&
			face[2] == 2 && position[2] == indexToCorner(w, 1)) {
		rotateLeftRightCorners(w);
	} else if (face[0] == 4 && position[0] == indexToCorner(w, 2) &&
			face[1] == 4 && position[1] == indexToCorner(w, 0) &&
			face[2] == 2 && position[2] == indexToCorner(w, 2)) {
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
	} else if (face[0] == 4 && position[0] == indexToCorner(w, 1) &&
			face[1] == 3 && position[1] == indexToCorner(w, 2) &&
			face[2] == 7 && position[2] == indexToCorner(w, 0)) {
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
		rotateLeftRightCorners(w);
	} else if (face[0] == 4 && position[0] == indexToCorner(w, 1) &&
			face[1] == 4 && position[1] == indexToCorner(w, 2) &&
			face[2] == 5 && position[2] == indexToCorner(w, 0)) {
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
	} else if (face[0] == 4 && position[0] == indexToCorner(w, 0) &&
			face[1] == 4 && position[1] == indexToCorner(w, 1) &&
			face[2] == 7 && position[2] == indexToCorner(w, 1)) {
		return;
	} else if (face[0] == 4 && position[0] == indexToCorner(w, 2) &&
			face[1] == 6 && position[1] == indexToCorner(w, 0) &&
			face[2] == 5 && position[2] == indexToCorner(w, 2)) {
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
		rotateLeftRightCorners(w);
	} else if (face[0] == 6 && position[0] == indexToCorner(w, 0) &&
			face[1] == 1 && position[1] == indexToCorner(w, 1) &&
			face[2] == 7 && position[2] == indexToCorner(w, 1)) {
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
		rotateLeftRightCorners(w);
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
	} else if (face[0] == 6 && position[0] == indexToCorner(w, 0) &&
			face[1] == 4 && position[1] == indexToCorner(w, 1) &&
			face[2] == 2 && position[2] == indexToCorner(w, 1)) {
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
		rotateLeftRightCorners(w);
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
	}
}

static void
rotateAroundCenter(OctWidget w, int face, int direction)
{
	int i;

	switch (face) {
	case 0:
		if (direction == CW) {
			for (i = 0; i < 3; i++) {
				movePuzzlePiece(w, 0, indexToCorner(w, 2),
					LEFT, PERIOD3, False);
				movePuzzlePiece(w, 7, indexToCorner(w, 2),
					BOTTOM, PERIOD3, False);
				movePuzzlePiece(w, 5, indexToCorner(w, 2),
					TOP, PERIOD3, False);
			}
			movePuzzlePiece(w, 0, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 6, indexToCorner(w, 2),
				RIGHT, PERIOD3, True);
		} else {
			for (i = 0; i < 3; i++) {
				movePuzzlePiece(w, 0, indexToCorner(w, 2),
					RIGHT, PERIOD3, False);
				movePuzzlePiece(w, 5, indexToCorner(w, 2),
					BOTTOM, PERIOD3, False);
				movePuzzlePiece(w, 7, indexToCorner(w, 2),
					TOP, PERIOD3, False);
			}
			movePuzzlePiece(w, 0, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 6, indexToCorner(w, 2),
				LEFT, PERIOD3, True);
		}
		break;
	case 1:
		if (direction == CW) {
			for (i = 0; i < 3; i++) {
				movePuzzlePiece(w, 1, indexToCorner(w, 2),
					TOP, PERIOD3, False);
				movePuzzlePiece(w, 6, indexToCorner(w, 2),
					RIGHT, PERIOD3, False);
				movePuzzlePiece(w, 4, indexToCorner(w, 2),
					LEFT, PERIOD3, False);
			}
			movePuzzlePiece(w, 1, indexToCorner(w, 2),
				TOP, PERIOD3, False);
			movePuzzlePiece(w, 5, indexToCorner(w, 2),
				TOP, PERIOD3, True);
		} else {
			for (i = 0; i < 3; i++) {
				movePuzzlePiece(w, 1, indexToCorner(w, 2),
					BOTTOM, PERIOD3, False);
				movePuzzlePiece(w, 4, indexToCorner(w, 2),
					RIGHT, PERIOD3, False);
				movePuzzlePiece(w, 6, indexToCorner(w, 2),
					LEFT, PERIOD3, False);
			}
			movePuzzlePiece(w, 1, indexToCorner(w, 2),
				BOTTOM, PERIOD3, False);
			movePuzzlePiece(w, 5, indexToCorner(w, 2),
				BOTTOM, PERIOD3, True);
		}
		break;
	case 2:
		if (direction == CW) {
			for (i = 0; i < 3; i++) {
				movePuzzlePiece(w, 2, indexToCorner(w, 2),
					RIGHT, PERIOD3, False);
				movePuzzlePiece(w, 5, indexToCorner(w, 2),
					TOP, PERIOD3, False);
				movePuzzlePiece(w, 7, indexToCorner(w, 2),
					BOTTOM, PERIOD3, False);
			}
			movePuzzlePiece(w, 2, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 4, indexToCorner(w, 2),
				LEFT, PERIOD3, True);
		} else {
			for (i = 0; i < 3; i++) {
				movePuzzlePiece(w, 2, indexToCorner(w, 2),
					LEFT, PERIOD3, False);
				movePuzzlePiece(w, 7, indexToCorner(w, 2),
					TOP, PERIOD3, False);
				movePuzzlePiece(w, 5, indexToCorner(w, 2),
					BOTTOM, PERIOD3, False);
			}
			movePuzzlePiece(w, 2, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 4, indexToCorner(w, 2),
				RIGHT, PERIOD3, True);
		}
		break;
	case 3:
		if (direction == CW) {
			for (i = 0; i < 3; i++) {
				movePuzzlePiece(w, 3, indexToCorner(w, 2),
					BOTTOM, PERIOD3, False);
				movePuzzlePiece(w, 4, indexToCorner(w, 2),
					LEFT, PERIOD3, False);
				movePuzzlePiece(w, 6, indexToCorner(w, 2),
					RIGHT, PERIOD3, False);
			}
			movePuzzlePiece(w, 3, indexToCorner(w, 2),
				BOTTOM, PERIOD3, False);
			movePuzzlePiece(w, 7, indexToCorner(w, 2),
				BOTTOM, PERIOD3, True);
		} else {
			for (i = 0; i < 3; i++) {
				movePuzzlePiece(w, 3, indexToCorner(w, 2),
					TOP, PERIOD3, False);
				movePuzzlePiece(w, 6, indexToCorner(w, 2),
					LEFT, PERIOD3, False);
				movePuzzlePiece(w, 4, indexToCorner(w, 2),
					RIGHT, PERIOD3, False);
			}
			movePuzzlePiece(w, 3, indexToCorner(w, 2),
				TOP, PERIOD3, False);
			movePuzzlePiece(w, 7, indexToCorner(w, 2),
				TOP, PERIOD3, True);
		}
		break;
	case 4:
		if (direction == CW) {
			for (i = 0; i < 3; i++) {
				movePuzzlePiece(w, 4, indexToCorner(w, 2),
					LEFT, PERIOD3, False);
				movePuzzlePiece(w, 3, indexToCorner(w, 2),
					BOTTOM, PERIOD3, False);
				movePuzzlePiece(w, 1, indexToCorner(w, 2),
					TOP, PERIOD3, False);
			}
			movePuzzlePiece(w, 4, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 2, indexToCorner(w, 2),
				RIGHT, PERIOD3, True);
		} else {
			for (i = 0; i < 3; i++) {
				movePuzzlePiece(w, 4, indexToCorner(w, 2),
					RIGHT, PERIOD3, False);
				movePuzzlePiece(w, 1, indexToCorner(w, 2),
					BOTTOM, PERIOD3, False);
				movePuzzlePiece(w, 3, indexToCorner(w, 2),
					TOP, PERIOD3, False);
			}
			movePuzzlePiece(w, 4, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 2, indexToCorner(w, 2),
				LEFT, PERIOD3, True);
		}
		break;
	case 5:
		if (direction == CW) {
			for (i = 0; i < 3; i++) {
				movePuzzlePiece(w, 5, indexToCorner(w, 2),
					TOP, PERIOD3, False);
				movePuzzlePiece(w, 2, indexToCorner(w, 2),
					RIGHT, PERIOD3, False);
				movePuzzlePiece(w, 0, indexToCorner(w, 2),
					LEFT, PERIOD3, False);
			}
			movePuzzlePiece(w, 5, indexToCorner(w, 2),
				TOP, PERIOD3, False);
			movePuzzlePiece(w, 1, indexToCorner(w, 2),
				TOP, PERIOD3, True);
		} else {
			for (i = 0; i < 3; i++) {
				movePuzzlePiece(w, 5, indexToCorner(w, 2),
					BOTTOM, PERIOD3, False);
				movePuzzlePiece(w, 0, indexToCorner(w, 2),
					RIGHT, PERIOD3, False);
				movePuzzlePiece(w, 2, indexToCorner(w, 2),
					LEFT, PERIOD3, False);
			}
			movePuzzlePiece(w, 5, indexToCorner(w, 2),
				BOTTOM, PERIOD3, False);
			movePuzzlePiece(w, 1, indexToCorner(w, 2),
				BOTTOM, PERIOD3, True);
		}
		break;
	case 6:
		if (direction == CW) {
			for (i = 0; i < 3; i++) {
				movePuzzlePiece(w, 6, indexToCorner(w, 2),
					RIGHT, PERIOD3, False);
				movePuzzlePiece(w, 1, indexToCorner(w, 2),
					TOP, PERIOD3, False);
				movePuzzlePiece(w, 3, indexToCorner(w, 2),
					BOTTOM, PERIOD3, False);
			}
			movePuzzlePiece(w, 6, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 0, indexToCorner(w, 2),
				LEFT, PERIOD3, True);
		} else {
			for (i = 0; i < 3; i++) {
				movePuzzlePiece(w, 6, indexToCorner(w, 2),
					LEFT, PERIOD3, False);
				movePuzzlePiece(w, 3, indexToCorner(w, 2),
					TOP, PERIOD3, False);
				movePuzzlePiece(w, 1, indexToCorner(w, 2),
					BOTTOM, PERIOD3, False);
			}
			movePuzzlePiece(w, 6, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 0, indexToCorner(w, 2),
				RIGHT, PERIOD3, True);
		}
		break;
	case 7:
		if (direction == CW) {
			for (i = 0; i < 3; i++) {
				movePuzzlePiece(w, 7, indexToCorner(w, 2),
					BOTTOM, PERIOD3, False);
				movePuzzlePiece(w, 0, indexToCorner(w, 2),
					LEFT, PERIOD3, False);
				movePuzzlePiece(w, 2, indexToCorner(w, 2),
					RIGHT, PERIOD3, False);
			}
			movePuzzlePiece(w, 7, indexToCorner(w, 2),
				BOTTOM, PERIOD3, False);
			movePuzzlePiece(w, 3, indexToCorner(w, 2),
				BOTTOM, PERIOD3, True);
		} else {
			for (i = 0; i < 3; i++) {
				movePuzzlePiece(w, 7, indexToCorner(w, 2),
					TOP, PERIOD3, False);
				movePuzzlePiece(w, 2, indexToCorner(w, 2),
					LEFT, PERIOD3, False);
				movePuzzlePiece(w, 0, indexToCorner(w, 2),
					RIGHT, PERIOD3, False);
			}
			movePuzzlePiece(w, 7, indexToCorner(w, 2),
				TOP, PERIOD3, False);
			movePuzzlePiece(w, 3, indexToCorner(w, 2),
				TOP, PERIOD3, True);
		}
		break;
	}
}

static void
rotate4Centers(OctWidget w, int nextFace)
{
	int i;

	switch (nextFace) {
	case 2:
		for (i = 0; i < 3; i++) {
			movePuzzlePiece(w, 1, indexToCorner(w, 0),
				TOP, PERIOD3, False);
			movePuzzlePiece(w, 3, indexToCorner(w, 0),
				TOP, PERIOD3, False);
			movePuzzlePiece(w, 1, indexToCorner(w, 0),
				BOTTOM, PERIOD3, False);
			movePuzzlePiece(w, 3, indexToCorner(w, 0),
				BOTTOM, PERIOD3, False);
		}
		break;
	case 3:
		for (i = 0; i < 3; i++) {
			movePuzzlePiece(w, 5, indexToCorner(w, 0),
				TOP, PERIOD3, False);
			movePuzzlePiece(w, 7, indexToCorner(w, 0),
				TOP, PERIOD3, False);
			movePuzzlePiece(w, 5, indexToCorner(w, 0),
				BOTTOM, PERIOD3, False);
			movePuzzlePiece(w, 7, indexToCorner(w, 0),
				BOTTOM, PERIOD3, False);
		}
		break;
	case 4:
		for (i = 0; i < 3; i++) {
			movePuzzlePiece(w, 5, indexToCorner(w, 0),
				TOP, PERIOD3, False);
			movePuzzlePiece(w, 7, indexToCorner(w, 0),
				BOTTOM, PERIOD3, False);
			movePuzzlePiece(w, 5, indexToCorner(w, 0),
				BOTTOM, PERIOD3, False);
			movePuzzlePiece(w, 7, indexToCorner(w, 0),
				TOP, PERIOD3, False);
		}
		break;
	case 5:
		for (i = 0; i < 3; i++) {
			movePuzzlePiece(w, 1, indexToCorner(w, 0),
				TOP, PERIOD3, False);
			movePuzzlePiece(w, 3, indexToCorner(w, 0),
				BOTTOM, PERIOD3, False);
			movePuzzlePiece(w, 1, indexToCorner(w, 0),
				BOTTOM, PERIOD3, False);
			movePuzzlePiece(w, 3, indexToCorner(w, 0),
				TOP, PERIOD3, False);
		}
		break;
	case 6:
		for (i = 0; i < 3; i++) {
			movePuzzlePiece(w, 7, indexToCorner(w, 0),
				TOP, PERIOD3, False);
			movePuzzlePiece(w, 5, indexToCorner(w, 0),
				BOTTOM, PERIOD3, False);
			movePuzzlePiece(w, 7, indexToCorner(w, 0),
				BOTTOM, PERIOD3, False);
			movePuzzlePiece(w, 5, indexToCorner(w, 0),
				TOP, PERIOD3, False);
		}
		break;
	case 7:
		for (i = 0; i < 3; i++) {
			movePuzzlePiece(w, 3, indexToCorner(w, 0),
				TOP, PERIOD3, False);
			movePuzzlePiece(w, 1, indexToCorner(w, 0),
				BOTTOM, PERIOD3, False);
			movePuzzlePiece(w, 3, indexToCorner(w, 0),
				BOTTOM, PERIOD3, False);
			movePuzzlePiece(w, 1, indexToCorner(w, 0),
				TOP, PERIOD3, False);
		}
		break;
	}
}

static void
solveTopEvenBottomOddCenters(OctWidget w)
{
	int color[4], face[4], i;

	color[0] = w->oct.facetLoc[0][0].face;
	color[1] = w->oct.facetLoc[2][0].face;
	color[2] = w->oct.facetLoc[5][0].face;
	color[3] = w->oct.facetLoc[7][0].face;

	for (i = 0; i < 4; i++) {
		face[i] = findPieceCenter(w, color[i], 0);
	}
#ifdef DEBUG
	(void) printf("solveTopEvenBottomOddCenters %d %d %d %d\n",
		face[0], face[1], face[2], face[3]);
#endif
	if (face[0] == 0 && face[1] == 2
			&& face[2] == 5 && face[3] == 7) {
		return;
	} else if (face[0] == 0 && face[1] == 5
			&& face[2] == 7 && face[3] == 2) {
		rotateAroundCenter(w, 4, CCW);
		return;
	} else if (face[0] == 0 && face[1] == 7
			&& face[2] == 2 && face[3] == 5) {
		rotateAroundCenter(w, 4, CW);
		return;
	} else if (face[0] == 2 && face[1] == 0
			&& face[2] == 7 && face[3] == 5) {
		rotate4Centers(w, 2);
		return;
	} else if (face[0] == 2 && face[1] == 5
			&& face[2] == 0 && face[3] == 7) {
		rotateAroundCenter(w, 1, CW);
		return;
	} else if (face[0] == 2 && face[1] == 7
			&& face[2] == 5 && face[3] == 0) {
		rotateAroundCenter(w, 3, CCW);
		return;
	} else if (face[0] == 5 && face[1] == 0
			&& face[2] == 2 && face[3] == 7) {
		rotateAroundCenter(w, 1, CCW);
		return;
	} else if (face[0] == 5 && face[1] == 2
			&& face[2] == 7 && face[3] == 0) {
		rotateAroundCenter(w, 6, CW);
		return;
	} else if (face[0] == 5 && face[1] == 7
			&& face[2] == 0 && face[3] == 2) {
		rotate4Centers(w, 5);
		return;
	} else if (face[0] == 7 && face[1] == 0
			&& face[2] == 5 && face[3] == 2) {
		rotateAroundCenter(w, 3, CW);
		return;
	} else if (face[0] == 7 && face[1] == 2
			&& face[2] == 0 && face[3] == 5) {
		rotateAroundCenter(w, 6, CCW);
		return;
	} else if (face[0] == 7 && face[1] == 5
			&& face[2] == 2 && face[3] == 0) {
		rotate4Centers(w, 7);
		return;
	}
}

static void
solveTopOddBottomEvenCenters(OctWidget w)
{
	int color[4], face[4], i;

	color[0] = w->oct.facetLoc[1][0].face;
	color[1] = w->oct.facetLoc[3][0].face;
	color[2] = w->oct.facetLoc[4][0].face;
	color[3] = w->oct.facetLoc[6][0].face;

	for (i = 0; i < 4; i++) {
		face[i] = findPieceCenter(w, color[i], 0);
	}
#ifdef DEBUG
	(void) printf("solveTopOddBottomEvenCenters %d %d %d %d\n",
		face[0], face[1], face[2], face[3]);
#endif
	if (face[0] == 1 && face[1] == 3
			&& face[2] == 4 && face[3] == 6) {
		return;
	} else if (face[0] == 1 && face[1] == 4
			&& face[2] == 6 && face[3] == 3) {
		rotateAroundCenter(w, 7, CCW);
		return;
	} else if (face[0] == 1 && face[1] == 6
			&& face[2] == 3 && face[3] == 4) {
		rotateAroundCenter(w, 7, CW);
		return;
	} else if (face[0] == 3 && face[1] == 1
			&& face[2] == 6 && face[3] == 4) {
		rotate4Centers(w, 3);
		return;
	} else if (face[0] == 3 && face[1] == 4
			&& face[2] == 1 && face[3] == 6) {
		rotateAroundCenter(w, 2, CW);
		return;
	} else if (face[0] == 3 && face[1] == 6
			&& face[2] == 4 && face[3] == 1) {
		rotateAroundCenter(w, 0, CCW);
		return;
	} else if (face[0] == 4 && face[1] == 1
			&& face[2] == 3 && face[3] == 6) {
		rotateAroundCenter(w, 2, CCW);
		return;
	} else if (face[0] == 4 && face[1] == 3
			&& face[2] == 6 && face[3] == 1) {
		rotateAroundCenter(w, 5, CW);
		return;
	} else if (face[0] == 4 && face[1] == 6
			&& face[2] == 1 && face[3] == 3) {
		rotate4Centers(w, 4);
		return;
	} else if (face[0] == 6 && face[1] == 1
			&& face[2] == 4 && face[3] == 3) {
		rotateAroundCenter(w, 0, CW);
		return;
	} else if (face[0] == 6 && face[1] == 3
			&& face[2] == 1 && face[3] == 4) {
		rotateAroundCenter(w, 5, CCW);
		return;
	} else if (face[0] == 6 && face[1] == 4
			&& face[2] == 3 && face[3] == 1) {
		rotate4Centers(w, 6);
		return;
	}
}

static void
rotateTopHalf(OctWidget w)
{
	int face = 0;
	int value = findPieceCenterOrient(w, face);

	if (value != 0) {
		Boolean opp = (value == 1);
#ifdef DEBUG
		(void) printf("rotateTopHalf %d %d\n", face, value);
#endif
		if (opp) {
			movePuzzlePiece(w, 5, indexToCorner(w, 2),
				BOTTOM, PERIOD3, False);
			movePuzzlePiece(w, 6, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 5, indexToCorner(w, 2),
				BOTTOM, PERIOD3, False);
			movePuzzlePiece(w, 6, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 5, indexToCorner(w, 2),
				TOP, PERIOD3, False);
			movePuzzlePiece(w, 6, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 5, indexToCorner(w, 2),
				TOP, PERIOD3, False);
			movePuzzlePiece(w, 6, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
		} else {
			movePuzzlePiece(w, 5, indexToCorner(w, 2),
				TOP, PERIOD3, False);
			movePuzzlePiece(w, 6, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 5, indexToCorner(w, 2),
				TOP, PERIOD3, False);
			movePuzzlePiece(w, 6, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 5, indexToCorner(w, 2),
				BOTTOM, PERIOD3, False);
			movePuzzlePiece(w, 6, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 5, indexToCorner(w, 2),
				BOTTOM, PERIOD3, False);
			movePuzzlePiece(w, 6, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
		}
	}
	face = 3;
	value = findPieceCenterOrient(w, face);
	if (value != 0) {
		Boolean opp = (value == 1);
#ifdef DEBUG
		(void) printf("rotateTopHalf %d %d\n", face, value);
#endif
		if (opp) {
			movePuzzlePiece(w, 4, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 2, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 4, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 2, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 4, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 2, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 4, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 2, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
		} else {
			movePuzzlePiece(w, 2, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 4, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 2, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 4, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 2, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 4, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 2, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 4, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
		}
	}
	face = 1;
	value = findPieceCenterOrient(w, face);
	if (value != 0) {
		Boolean opp = (value == 1);
#ifdef DEBUG
		(void) printf("rotateTopHalf %d %d\n", face, value);
#endif
		if (opp) {
			movePuzzlePiece(w, 2, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 4, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 2, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 4, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 2, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 4, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 2, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 4, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
		} else {
			movePuzzlePiece(w, 4, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 2, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 4, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 2, indexToCorner(w, 2),
				RIGHT, PERIOD3, False);
			movePuzzlePiece(w, 4, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 2, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 4, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
			movePuzzlePiece(w, 2, indexToCorner(w, 2),
				LEFT, PERIOD3, False);
		}
	}
	face = 2;
	value = findPieceCenterOrient(w, face);
	if (value != 0) {
		int i;
		Boolean opp = (value == 1);
#ifdef DEBUG
		(void) printf("rotateTopHalf %d %d\n", face, value);
#endif
		if (opp) {
			for (i = 0; i < 10; i++) {
				movePuzzlePiece(w, 4, indexToCorner(w, 2),
					RIGHT, PERIOD3, False);
				movePuzzlePiece(w, 1, indexToCorner(w, 2),
					BOTTOM, PERIOD3, False);
				movePuzzlePiece(w, 3, indexToCorner(w, 2),
					TOP, PERIOD3, False);
			}
		} else {
			for (i = 0; i < 10; i++) {
				movePuzzlePiece(w, 4, indexToCorner(w, 2),
					LEFT, PERIOD3, False);
				movePuzzlePiece(w, 3, indexToCorner(w, 2),
					BOTTOM, PERIOD3, False);
				movePuzzlePiece(w, 1, indexToCorner(w, 2),
					TOP, PERIOD3, False);
			}
		}
	}
}

static void
bottomTriangleTwister(OctWidget w, int direction)
{
	switch (direction) {
	case TR:
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
		break;
	case BR:
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToCorner(w, 2),
			TOP, PERIOD3, False);
		break;
	case BL:
		movePuzzlePiece(w, 1, indexToCorner(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToCorner(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToCorner(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToCorner(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
		break;
	case TL:
		movePuzzlePiece(w, 0, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToCorner(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToCorner(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToCorner(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToCorner(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToCorner(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToCorner(w, 2),
			BOTTOM, PERIOD3, False);
		break;
	}
}

static void
rotateBottomHalf(OctWidget w)
{
	int value[4], i;

	for (i = 0; i < 4; i++)
		value[i] = findPieceCenterOrient(w, i + 4);
#ifdef DEBUG
	(void) printf("rotateBottomHalf %d%d%d%d\n",
		value[0], value[1], value[2], value[3]);
#endif
	if (value[0] == 0 && value[1] == 0 &&
			value[2] == 0 && value[3] == 0) {
		return;
	} else if (value[0] == 0 && value[1] == 1 &&
			value[2] == 0 && value[3] == 2) {
		bottomTriangleTwister(w, TR);
		bottomTriangleTwister(w, BR);
	} else if (value[0] == 0 && value[1] == 2 &&
			value[2] == 0 && value[3] == 1) {
		bottomTriangleTwister(w, TL);
		bottomTriangleTwister(w, BL);
	} else if (value[0] == 1 && value[1] == 0 &&
			value[2] == 2 && value[3] == 0) {
		bottomTriangleTwister(w, TR);
		bottomTriangleTwister(w, TL);
	} else if (value[0] == 1 && value[1] == 1 &&
			value[2] == 2 && value[3] == 2) {
		bottomTriangleTwister(w, BL);
	} else if (value[0] == 1 && value[1] == 2 &&
			value[2] == 2 && value[3] == 1) {
		bottomTriangleTwister(w, BR);
	} else if (value[0] == 2 && value[1] == 0 &&
			value[2] == 1 && value[3] == 0) {
		bottomTriangleTwister(w, BR);
		bottomTriangleTwister(w, BL);
	} else if (value[0] == 2 && value[1] == 1 &&
			value[2] == 1 && value[3] == 2) {
		bottomTriangleTwister(w, TL);
	} else if (value[0] == 2 && value[1] == 2 &&
			value[2] == 1 && value[3] == 1) {
		bottomTriangleTwister(w, TR);
	}
}

static void
simpleEdgeMove(OctWidget w, int face0, int dir0,
		int face1, int dir1) {
	int position = indexToCorner(w, 2);
	int i;

	for (i = 0; i < 4; i++) {
		movePuzzlePiece(w, face0, position,
			dir0, PERIOD3, False);
		movePuzzlePiece(w, face1, position,
			dir1, PERIOD3, False);
		movePuzzlePiece(w, face0, position,
			oppDir(dir0), PERIOD3, False);
		movePuzzlePiece(w, face1, position,
			oppDir(dir1), PERIOD3, False);
	}
}

static void
edge0Pos2(OctWidget w, int face, int position) {
	if (face == 1 && edgeToIndex(w, position) == 0) {
		movePuzzlePiece(w, 1, indexToEdge(w, 1),
			TOP, PERIOD3, False);
	} else if (face == 1 && edgeToIndex(w, position) == 1) {
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToEdge(w, 1),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	} else if (face == 1 && edgeToIndex(w, position) == 2) {
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToEdge(w, 1),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	} else if (face == 3 && edgeToIndex(w, position) == 0) {
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToEdge(w, 1),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	} else if (face == 3 && edgeToIndex(w, position) == 1) {
		movePuzzlePiece(w, 3, indexToEdge(w, 1),
			TOP, PERIOD3, False);
	} else if (face == 3 && edgeToIndex(w, position) == 2) {
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToEdge(w, 1),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	} else if (face == 4 && edgeToIndex(w, position) == 0) {
		movePuzzlePiece(w, 5, indexToEdge(w, 0),
			BOTTOM, PERIOD3, False);
	} else if (face == 4 && edgeToIndex(w, position) == 1) {
		movePuzzlePiece(w, 7, indexToEdge(w, 0),
			BOTTOM, PERIOD3, False);
	} else if (face == 4 && edgeToIndex(w, position) == 2) {
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 5, indexToEdge(w, 1),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	} else if (face == 6 && edgeToIndex(w, position) == 0) {
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 7, indexToEdge(w, 0),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	} else if (face == 6 && edgeToIndex(w, position) == 1) {
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 5, indexToEdge(w, 1),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	} else if (face == 6 && edgeToIndex(w, position) == 2) {
		return;
	}
}

static void
edge0Pos0(OctWidget w, int face, int position) {
	if (face == 1 && edgeToIndex(w, position) == 0) {
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToEdge(w, 0),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	} else if (face == 1 && edgeToIndex(w, position) == 1) {
		return;
	} else if (face == 1 && edgeToIndex(w, position) == 2) {
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToEdge(w, 0),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	} else if (face == 3 && edgeToIndex(w, position) == 0) {
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToEdge(w, 0),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	} else if (face == 3 && edgeToIndex(w, position) == 1) {
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToEdge(w, 0),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	} else if (face == 3 && edgeToIndex(w, position) == 2) {
		movePuzzlePiece(w, 0, indexToEdge(w, 0),
			RIGHT, PERIOD3, False);
	} else if (face == 4 && edgeToIndex(w, position) == 0) {
		movePuzzlePiece(w, 0, indexToEdge(w, 0),
			LEFT, PERIOD3, False);
	} else if (face == 4 && edgeToIndex(w, position) == 1) {
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToEdge(w, 0),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	} else if (face == 4 && edgeToIndex(w, position) == 2) {
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToEdge(w, 0),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	} else if (face == 6 && edgeToIndex(w, position) == 0) {
		movePuzzlePiece(w, 6, indexToEdge(w, 0),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToEdge(w, 0),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 6, indexToEdge(w, 0),
			LEFT, PERIOD3, False);
	} else if (face == 6 && edgeToIndex(w, position) == 1) {
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToEdge(w, 0),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	} else if (face == 6 && edgeToIndex(w, position) == 2) {
		(void) printf("cannot get here\n");
	}
}

static void
edge0Pos1(OctWidget w, int face, int position) {
	if (face == 1 && edgeToIndex(w, position) == 0) {
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		simpleEdgeMove(w, 7, BOTTOM, 4, LEFT);
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	} else if (face == 1 && edgeToIndex(w, position) == 1) {
		(void) printf("cannot get here\n");
	} else if (face == 1 && edgeToIndex(w, position) == 2) {
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		simpleEdgeMove(w, 7, BOTTOM, 4, LEFT);
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	} else if (face == 3 && edgeToIndex(w, position) == 0) {
		return;
	} else if (face == 3 && edgeToIndex(w, position) == 1) {
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		simpleEdgeMove(w, 7, BOTTOM, 4, LEFT);
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	} else if (face == 3 && edgeToIndex(w, position) == 2) {
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToEdge(w, 1),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	} else if (face == 4 && edgeToIndex(w, position) == 0) {
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		simpleEdgeMove(w, 7, BOTTOM, 4, LEFT);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	} else if (face == 4 && edgeToIndex(w, position) == 1) {
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToEdge(w, 1),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	} else if (face == 4 && edgeToIndex(w, position) == 2) {
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToEdge(w, 1),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	} else if (face == 6 && edgeToIndex(w, position) == 0) {
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToEdge(w, 1),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	} else if (face == 6 && edgeToIndex(w, position) == 1) {
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		simpleEdgeMove(w, 7, BOTTOM, 4, LEFT);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	} else if (face == 6 && edgeToIndex(w, position) == 2) {
		(void) printf("cannot get here\n");
	}
}

static void
edge1Pos2(OctWidget w, int face, int position)
{
	if (face == 2 && edgeToIndex(w, position) == 0) {
		movePuzzlePiece(w, 2, indexToEdge(w, 0),
			RIGHT, PERIOD3, False);
	} else if (face == 2 && edgeToIndex(w, position) == 1) {
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToEdge(w, 0),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	} else if (face == 2 && edgeToIndex(w, position) == 2) {
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToEdge(w, 0),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	} else if (face == 5 && edgeToIndex(w, position) == 0) {
		simpleEdgeMove(w, 0, LEFT, 1, TOP);
	} else if (face == 5 && edgeToIndex(w, position) == 1) {
		simpleEdgeMove(w, 2, LEFT, 1, BOTTOM);
	} else if (face == 5 && edgeToIndex(w, position) == 2) {
		return;
	} else if (face == 7 && edgeToIndex(w, position) == 0) {
		simpleEdgeMove(w, 1, BOTTOM, 2, LEFT);
	} else if (face == 7 && edgeToIndex(w, position) == 1) {
		movePuzzlePiece(w, 2, indexToEdge(w, 0),
			LEFT, PERIOD3, False);
	} else if (face == 7 && edgeToIndex(w, position) == 2) {
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		simpleEdgeMove(w, 1, TOP, 0, LEFT);
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	}
}

static void
edge3Pos2(OctWidget w, int face, int position)
{
	if (face == 2 && edgeToIndex(w, position) == 0) {
		simpleEdgeMove(w, 4, RIGHT, 7, TOP);
	} else if (face == 2 && edgeToIndex(w, position) == 1) {
		simpleEdgeMove(w, 7, TOP, 4, RIGHT);
	} else if (face == 2 && edgeToIndex(w, position) == 2) {
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		simpleEdgeMove(w, 3, BOTTOM, 2, RIGHT);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	} else if (face == 5 && edgeToIndex(w, position) == 0) {
		simpleEdgeMove(w, 3, TOP, 0, RIGHT);
	} else if (face == 5 && edgeToIndex(w, position) == 1) {
		simpleEdgeMove(w, 3, BOTTOM, 2, RIGHT);
	} else if (face == 7 && edgeToIndex(w, position) == 0) {
		simpleEdgeMove(w, 2, RIGHT, 3, BOTTOM);
	} else if (face == 7 && edgeToIndex(w, position) == 1) {
		simpleEdgeMove(w, 0, RIGHT, 3, TOP);
	} else if (face == 7 && edgeToIndex(w, position) == 2) {
		return;
	}
}

static void
edge1Pos0(OctWidget w, int face, int position)
{
	if (face == 2 && edgeToIndex(w, position) == 0) {
		simpleEdgeMove(w, 2, LEFT, 4, RIGHT);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		simpleEdgeMove(w, 4, LEFT, 2, RIGHT);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	} else if (face == 2 && edgeToIndex(w, position) == 1) {
		return;
	} else if (face == 2 && edgeToIndex(w, position) == 2) {
		simpleEdgeMove(w, 2, RIGHT, 4, LEFT);
	} else if (face == 5 && edgeToIndex(w, position) == 0) {
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		simpleEdgeMove(w, 4, LEFT, 2, RIGHT);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	} else if (face == 5 && edgeToIndex(w, position) == 1) {
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		simpleEdgeMove(w, 4, LEFT, 2, RIGHT);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	} else if (face == 7 && edgeToIndex(w, position) == 0) {
		simpleEdgeMove(w, 4, LEFT, 2, RIGHT);
	} else if (face == 7 && edgeToIndex(w, position) == 1) {
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		simpleEdgeMove(w, 4, LEFT, 2, RIGHT);
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	}
}

static void
edge3Pos1(OctWidget w, int face, int position)
{
	if (face == 2 && edgeToIndex(w, position) == 0) {
		return;
	} else if (face == 2 && edgeToIndex(w, position) == 2) {
		simpleEdgeMove(w, 2, LEFT, 4, RIGHT);
	} else if (face == 5 && edgeToIndex(w, position) == 0) {
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		simpleEdgeMove(w, 4, RIGHT, 2, LEFT);
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	} else if (face == 5 && edgeToIndex(w, position) == 1) {
		simpleEdgeMove(w, 4, RIGHT, 2, LEFT);
	} else if (face == 7 && edgeToIndex(w, position) == 0) {
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		simpleEdgeMove(w, 4, RIGHT, 2, LEFT);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	} else if (face == 7 && edgeToIndex(w, position) == 1) {
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		simpleEdgeMove(w, 4, RIGHT, 2, LEFT);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	}
}

static void
edge5Pos0(OctWidget w, int face, int position)
{
	if (face == 4 && edgeToIndex(w, position) == 0) {
		simpleEdgeMove(w, 2, RIGHT, 1, TOP);
	} else if (face == 4 && edgeToIndex(w, position) == 1) {
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		simpleEdgeMove(w, 2, RIGHT, 1, TOP);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	} else if (face == 4 && edgeToIndex(w, position) == 2) {
		simpleEdgeMove(w, 1, TOP, 2, RIGHT);
	} else if (face == 6 && edgeToIndex(w, position) == 0) {
		simpleEdgeMove(w, 2, LEFT, 3, TOP);
		simpleEdgeMove(w, 1, TOP, 2, RIGHT);
	} else if (face == 6 && edgeToIndex(w, position) == 1) {
		return;
	}
}

static void
edge5Pos1(OctWidget w, int face, int position)
{
	if (face == 4 && edgeToIndex(w, position) == 0) {
		return;
	} else if (face == 4 && edgeToIndex(w, position) == 1) {
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		simpleEdgeMove(w, 2, LEFT, 3, TOP);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	} else if (face == 4 && edgeToIndex(w, position) == 2) {
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		simpleEdgeMove(w, 3, TOP, 2, LEFT);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	} else if (face == 6 && edgeToIndex(w, position) == 0) {
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		simpleEdgeMove(w, 2, LEFT, 3, TOP);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	}
}

static void
edge2Pos2(OctWidget w, int face, int position)
{
	if (face == 4 && edgeToIndex(w, position) == 1) {
		simpleEdgeMove(w, 3, TOP, 2, LEFT);
	} else if (face == 4 && edgeToIndex(w, position) == 2) {
		return;
	} else if (face == 6 && edgeToIndex(w, position) == 0) {
		simpleEdgeMove(w, 2, LEFT, 3, TOP);
	}
}

static void
solveTopEdges(OctWidget w)
{
	int topColor = w->oct.facetLoc[0][0].face;
	int otherColor = w->oct.facetLoc[6][0].face;
	int face, position;
	findPiece(w, otherColor, topColor, &face, &position);
#ifdef DEBUG
	(void) printf("Top face %d, position %d\n", face, position);
#endif
	edge0Pos2(w, face, position);
	otherColor = w->oct.facetLoc[1][0].face;
	findPiece(w, otherColor, topColor, &face, &position);
#ifdef DEBUG
	(void) printf("Right face %d, position %d\n", face, position);
#endif
	edge0Pos0(w, face, position);
	otherColor = w->oct.facetLoc[3][0].face;
	findPiece(w, otherColor, topColor, &face, &position);
#ifdef DEBUG
	(void) printf("Left face %d, position %d\n", face, position);
#endif
	edge0Pos1(w, face, position);
}

static void
solveMiddleEdges(OctWidget w)
{
	int sideColor = w->oct.facetLoc[1][0].face;
	int otherColor = w->oct.facetLoc[5][0].face;
	int face, position;
	findPiece(w, otherColor, sideColor, &face, &position);
#ifdef DEBUG
	(void) printf("Right face %d, position %d\n", face, position);
#endif
	edge1Pos2(w, face, position);
	sideColor = w->oct.facetLoc[3][0].face;
	otherColor = w->oct.facetLoc[7][0].face;
	findPiece(w, otherColor, sideColor, &face, &position);
#ifdef DEBUG
	(void) printf("Left face %d, position %d\n", face, position);
#endif
	edge3Pos2(w, face, position);
	sideColor = w->oct.facetLoc[1][0].face;
	otherColor = w->oct.facetLoc[2][0].face;
	findPiece(w, otherColor, sideColor, &face, &position);
#ifdef DEBUG
	(void) printf("Right face %d, position %d\n", face, position);
#endif
	edge1Pos0(w, face, position);
	sideColor = w->oct.facetLoc[3][0].face;
	otherColor = w->oct.facetLoc[2][0].face;
	findPiece(w, otherColor, sideColor, &face, &position);
#ifdef DEBUG
	(void) printf("Left face %d, position %d\n", face, position);
#endif
	edge3Pos1(w, face, position);
}

static void
solveBottomEdges(OctWidget w)
{
	int sideColor = w->oct.facetLoc[5][0].face;
	int otherColor = w->oct.facetLoc[6][0].face;
	int face, position;
	findPiece(w, otherColor, sideColor, &face, &position);
#ifdef DEBUG
	(void) printf("Bottom face %d, position %d\n", face, position);
#endif
	edge5Pos0(w, face, position);
	otherColor = w->oct.facetLoc[4][0].face;
	findPiece(w, otherColor, sideColor, &face, &position);
#ifdef DEBUG
	(void) printf("Top face %d, position %d\n", face, position);
#endif
	edge5Pos1(w, face, position);
	sideColor = w->oct.facetLoc[2][0].face;
	otherColor = w->oct.facetLoc[4][0].face;
	findPiece(w, otherColor, sideColor, &face, &position);
#ifdef DEBUG
	(void) printf("Last face %d, position %d\n", face, position);
#endif
	edge2Pos2(w, face, position);
}

static int centerFaces[3];
static int centerPositions[3];
static int centerRotations[3];

static void
findCenterPositions(OctWidget w, int color)
{
	int face, position, positionIndex, i = 0;

	for (face = 0; face < MAX_FACES; face++) {
		for (positionIndex = 0; positionIndex < 3; positionIndex++) {
			position = indexToCenter(w, positionIndex);
			if (w->oct.facetLoc[face][position].face == color) {
				centerFaces[i] = face;
				centerPositions[i] = position;
				i++;
				if (i >= 3)
					return;
			}
		}
	}
}

static void
findCenterPositionsRev(OctWidget w, int color)
{
	int face, position, positionIndex, i = 0;

	for (face = MAX_FACES - 1; face >= 0; face--) {
		for (positionIndex = 0; positionIndex < 3; positionIndex++) {
			position = indexToCenter(w, positionIndex);
			if (w->oct.facetLoc[face][position].face == color) {
				centerFaces[i] = face;
				centerPositions[i] = position;
				i++;
				if (i >= 3)
					return;
			}
		}
	}
}

static void
simpleCenterSwap(OctWidget w, int face0, int dir0,
		int face1, int dir1) {
	int facePosition = indexToEdge(w, 2);
	int centerPosition = indexToEdge(w, 0);
	int i;

	for (i = 0; i < 5; i++) {
		movePuzzlePiece(w, face0, facePosition,
			dir0, PERIOD3, False);
		movePuzzlePiece(w, face1, centerPosition,
			dir1, PERIOD3, False);
		movePuzzlePiece(w, face0, facePosition,
			oppDir(dir0), PERIOD3, False);
		movePuzzlePiece(w, face1, centerPosition,
			oppDir(dir1), PERIOD3, False);
	}
}

static void
solve2To0Faces(OctWidget w, int sourcePosition, int targetPosition)
{
#ifdef DEBUG
	(void) printf("20 sp=%d tp=%d\n", sourcePosition, targetPosition);
#endif
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	simpleCenterSwap(w, 4, RIGHT, 1, BOTTOM);
	/* (0, 1):= (2, 1), (2, 2):= (0, 1), (2, 1):= (2, 2) */
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
}

static void
solve5To0Faces(OctWidget w, int sourcePosition, int targetPosition)
{
#ifdef DEBUG
	(void) printf("50 sp=%d tp=%d\n", sourcePosition, targetPosition);
#endif
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	simpleCenterSwap(w, 1, TOP, 3, TOP);
	/* (0, 2):= (5, 1), (5, 0):= (0, 2), (5, 1):= (5, 0) */
	if (targetPosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
}

static void
solve7To0Faces(OctWidget w, int sourcePosition, int targetPosition)
{
#ifdef DEBUG
	(void) printf("70 sp=%d tp=%d\n", sourcePosition, targetPosition);
#endif
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	simpleCenterSwap(w, 3, TOP, 1, TOP);
	/* (0, 2):= (5, 1), (5, 0):= (0, 2), (5, 1):= (5, 0) */
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
}

static void
solve5To2Faces(OctWidget w, int sourcePosition, int targetPosition)
{
#ifdef DEBUG
	(void) printf("52 sp=%d tp=%d\n", sourcePosition, targetPosition);
#endif
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	simpleCenterSwap(w, 1, BOTTOM, 3, BOTTOM);
	/* (2, 1):= (5, 2), (5, 0):= (2, 1), (5, 2):= (5, 0) */
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
}

static void
solve7To2Faces(OctWidget w, int sourcePosition, int targetPosition)
{
#ifdef DEBUG
	(void) printf("72 sp=%d tp=%d\n", sourcePosition, targetPosition);
#endif
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	simpleCenterSwap(w, 3, BOTTOM, 1, BOTTOM);
	/* (2, 2):= (7, 1), (7, 0):= (2, 2), (7, 1):= (7, 0) */
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			TOP, PERIOD3, False);
}

static void
solve7To5Faces(OctWidget w, int sourcePosition, int targetPosition)
{
#ifdef DEBUG
	(void) printf("75 sp=%d tp=%d\n", sourcePosition, targetPosition);
#endif
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	simpleCenterSwap(w, 3, BOTTOM, 0, RIGHT);
	/* (5, 2):= (7, 2), (7, 1):= (5, 2), (7, 2):= (7, 1) */
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
}

static void
solve4To6Faces(OctWidget w, int sourcePosition, int targetPosition)
{
#ifdef DEBUG
	(void) printf("46 sp=%d tp=%d\n", sourcePosition, targetPosition);
#endif
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	simpleCenterSwap(w, 2, LEFT, 7, TOP);
	/* (6, 1):= (4, 1), (4, 2):= (6, 1), (4, 1):= (4, 2) */
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
}

static void
solve3To6Faces(OctWidget w, int sourcePosition, int targetPosition)
{
#ifdef DEBUG
	(void) printf("36 sp=%d tp=%d\n", sourcePosition, targetPosition);
#endif
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	simpleCenterSwap(w, 7, BOTTOM, 5, BOTTOM);
	/* (6, 2):= (3, 1), (3, 0):= (6, 2), (3, 1):= (3, 0) */
	if (targetPosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
}

static void
solve1To6Faces(OctWidget w, int sourcePosition, int targetPosition)
{
#ifdef DEBUG
	(void) printf("16 sp=%d tp=%d\n", sourcePosition, targetPosition);
#endif
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	simpleCenterSwap(w, 5, BOTTOM, 7, BOTTOM);
	/* (6, 2):= (3, 1), (3, 0):= (6, 2), (3, 1):= (3, 0) */
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			TOP, PERIOD3, False);
}

static void
solve3To4Faces(OctWidget w, int sourcePosition, int targetPosition)
{
#ifdef DEBUG
	(void) printf("34 sp=%d tp=%d\n", sourcePosition, targetPosition);
#endif
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	simpleCenterSwap(w, 7, TOP, 5, TOP);
	/* (4, 1):= (3, 2), (3, 0):= (4, 1), (3, 2):= (3, 0) */
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
}

static void
solve1To4Faces(OctWidget w, int sourcePosition, int targetPosition)
{
#ifdef DEBUG
	(void) printf("14 sp=%d tp=%d\n", sourcePosition, targetPosition);
#endif
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	simpleCenterSwap(w, 5, TOP, 7, TOP);
	/* (4, 2):= (1, 1), (1, 0):= (4, 2), (1, 1):= (1, 0) */
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
}

static void
solve1To3Faces(OctWidget w, int sourcePosition, int targetPosition)
{
#ifdef DEBUG
	(void) printf("13 sp=%d tp=%d\n", sourcePosition, targetPosition);
#endif
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	simpleCenterSwap(w, 5, TOP, 6, LEFT);
	/* (3, 2):= (1, 2), (1, 1):= (3, 2), (1, 2):= (1, 1) */
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	if (sourcePosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	else if (sourcePosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			TOP, PERIOD3, False);
}

static void
solve0Faces(OctWidget w)
{
	int count;
	int sourcePosition, targetPosition;
	int sourceFace, targetFace = 0;
	int color = w->oct.facetLoc[targetFace][0].face;

#ifdef DEBUG
	(void) printf("targetFace %d\n", targetFace);
#endif
	for (count = 0; count < 3; count++) {
		int sourceCount = 0, targetCount = 0;

		findCenterPositions(w, color);
#ifdef DEBUG
		(void) printf("face0=%d, position0=%d; face1=%d, position1=%d; face2=%d, position2=%d\n",
			centerFaces[0], centerPositions[0],
			centerFaces[1], centerPositions[1],
			centerFaces[2], centerPositions[2]);
#endif
		if (centerFaces[count] == 2) {
			sourceFace = 2;
			while (w->oct.facetLoc[targetFace][indexToCenter(w, targetCount)].face == color) {
				targetCount++;
				if (targetCount >= 3)
					return;
			}
			while (centerFaces[sourceCount] != sourceFace) {
				sourceCount++;
				if (sourceCount >= 3)
					return;
			}
#ifdef DEBUG
			(void) printf("%d: face0=%d, position0=%d; face1=%d, position1=%d; face2=%d, position2=%d, targetCount %d, sourceCount %d\n",
				sourceFace, centerFaces[0], centerPositions[0],
				centerFaces[1], centerPositions[1],
				centerFaces[2], centerPositions[2],
				targetCount, sourceCount);
#endif
			if (centerFaces[sourceCount] == sourceFace) {
				sourcePosition = centerPositions[sourceCount];
				targetPosition = indexToCenter(w, targetCount);
				solve2To0Faces(w, sourcePosition, targetPosition);
			}
		} else if (centerFaces[count] == 5) {
			sourceFace = 5;
			while (w->oct.facetLoc[targetFace][indexToCenter(w, targetCount)].face == color) {
				targetCount++;
				if (targetCount >= 3)
					return;
			}
			while (centerFaces[sourceCount] != sourceFace) {
				sourceCount++;
				if (sourceCount >= 3)
					return;
			}
#ifdef DEBUG
			(void) printf("%d: face0=%d, position0=%d; face1=%d, position1=%d; face2=%d, position2=%d, targetCount %d, sourceCount %d\n",
				sourceFace, centerFaces[0], centerPositions[0],
				centerFaces[1], centerPositions[1],
				centerFaces[2], centerPositions[2],
				targetCount, sourceCount);
#endif
			if (centerFaces[sourceCount] == sourceFace) {
				sourcePosition = centerPositions[sourceCount];
				targetPosition = indexToCenter(w, targetCount);
				solve5To0Faces(w, sourcePosition, targetPosition);
			}
		} else if (centerFaces[count] == 7) {
			sourceFace = 7;
			while (w->oct.facetLoc[targetFace][indexToCenter(w, targetCount)].face == color) {
				targetCount++;
				if (targetCount >= 3)
					return;
			}
			while (centerFaces[sourceCount] != sourceFace) {
				sourceCount++;
				if (sourceCount >= 3)
					return;
			}
#ifdef DEBUG
			(void) printf("%d: face0=%d, position0=%d; face1=%d, position1=%d; face2=%d, position2=%d, targetCount %d, sourceCount %d\n",
				sourceFace, centerFaces[0], centerPositions[0],
				centerFaces[1], centerPositions[1],
				centerFaces[2], centerPositions[2],
				targetCount, sourceCount);
#endif
			if (centerFaces[sourceCount] == sourceFace) {
				sourcePosition = centerPositions[sourceCount];
				targetPosition = indexToCenter(w, targetCount);
				solve7To0Faces(w, sourcePosition, targetPosition);
			}
		}
	}
}

static void
solve2Faces(OctWidget w)
{
	int count;
	int sourcePosition, targetPosition;
	int sourceFace, targetFace = 2;
	int color = w->oct.facetLoc[targetFace][0].face;

#ifdef DEBUG
	(void) printf("targetFace %d\n", targetFace);
#endif
	for (count = 0; count < 3; count++) {
		int sourceCount = 0, targetCount = 0;

		findCenterPositions(w, color);
#ifdef DEBUG
		(void) printf("face0=%d, position0=%d; face1=%d, position1=%d; face2=%d, position2=%d\n",
			centerFaces[0], centerPositions[0],
			centerFaces[1], centerPositions[1],
			centerFaces[2], centerPositions[2]);
#endif
		if (centerFaces[count] == 5) {
			sourceFace = 5;
			while (w->oct.facetLoc[targetFace][indexToCenter(w, targetCount)].face == color) {
				targetCount++;
				if (targetCount >= 3)
					return;
			}
			while (centerFaces[sourceCount] != sourceFace) {
				sourceCount++;
				if (sourceCount >= 3)
					return;
			}
#ifdef DEBUG
			(void) printf("%d: face0=%d, position0=%d; face1=%d, position1=%d; face2=%d, position2=%d, targetCount %d, sourceCount %d\n",
				sourceFace, centerFaces[0], centerPositions[0],
				centerFaces[1], centerPositions[1],
				centerFaces[2], centerPositions[2],
				targetCount, sourceCount);
#endif
			if (centerFaces[sourceCount] == sourceFace) {
				sourcePosition = centerPositions[sourceCount];
				targetPosition = indexToCenter(w, targetCount);
				solve5To2Faces(w, sourcePosition, targetPosition);
			}
		} else if (centerFaces[count] == 7) {
			sourceFace = 7;
			while (w->oct.facetLoc[targetFace][indexToCenter(w, targetCount)].face == color) {
				targetCount++;
				if (targetCount >= 3)
					return;
			}
			while (centerFaces[sourceCount] != sourceFace) {
				sourceCount++;
				if (sourceCount >= 3)
					return;
			}
#ifdef DEBUG
			(void) printf("%d: face0=%d, position0=%d; face1=%d, position1=%d; face2=%d, position2=%d, targetCount %d, sourceCount %d\n",
				sourceFace, centerFaces[0], centerPositions[0],
				centerFaces[1], centerPositions[1],
				centerFaces[2], centerPositions[2],
				targetCount, sourceCount);
#endif
			if (centerFaces[sourceCount] == sourceFace) {
				sourcePosition = centerPositions[sourceCount];
				targetPosition = indexToCenter(w, targetCount);
				solve7To2Faces(w, sourcePosition, targetPosition);
			}
		}
	}
}

static void
solve5Faces(OctWidget w)
{
	int count;
	int sourcePosition, targetPosition;
	int sourceFace, targetFace = 5;
	int color = w->oct.facetLoc[targetFace][0].face;

#ifdef DEBUG
	(void) printf("targetFace %d\n", targetFace);
#endif
	for (count = 0; count < 3; count++) {
		int sourceCount = 0, targetCount = 0;

		findCenterPositions(w, color);
#ifdef DEBUG
		(void) printf("face0=%d, position0=%d; face1=%d, position1=%d; face2=%d, position2=%d\n",
			centerFaces[0], centerPositions[0],
			centerFaces[1], centerPositions[1],
			centerFaces[2], centerPositions[2]);
#endif
		if (centerFaces[count] == 7) {
			sourceFace = 7;
			while (w->oct.facetLoc[targetFace][indexToCenter(w, targetCount)].face == color) {
				targetCount++;
				if (targetCount >= 3)
					return;
			}
			while (centerFaces[sourceCount] != sourceFace) {
				sourceCount++;
				if (sourceCount >= 3)
					return;
			}
#ifdef DEBUG
			(void) printf("%d: face0=%d, position0=%d; face1=%d, position1=%d; face2=%d, position2=%d, targetCount %d, sourceCount %d\n",
				sourceFace, centerFaces[0], centerPositions[0],
				centerFaces[1], centerPositions[1],
				centerFaces[2], centerPositions[2],
				targetCount, sourceCount);
#endif
			if (centerFaces[sourceCount] == sourceFace) {
				sourcePosition = centerPositions[sourceCount];
				targetPosition = indexToCenter(w, targetCount);
				solve7To5Faces(w, sourcePosition, targetPosition);
			}
		}
	}
}

static void
solve6Faces(OctWidget w)
{
	int count;
	int sourcePosition, targetPosition;
	int sourceFace, targetFace = 6;
	int color = w->oct.facetLoc[targetFace][0].face;

#ifdef DEBUG
	(void) printf("targetFace %d\n", targetFace);
#endif
	for (count = 0; count < 3; count++) {
		int sourceCount = 0, targetCount = 0;

		findCenterPositionsRev(w, color);
#ifdef DEBUG
		(void) printf("face0=%d, position0=%d; face1=%d, position1=%d; face2=%d, position2=%d\n",
			centerFaces[0], centerPositions[0],
			centerFaces[1], centerPositions[1],
			centerFaces[2], centerPositions[2]);
#endif
		if (centerFaces[count] == 4) {
			sourceFace = 4;
			while (w->oct.facetLoc[targetFace][indexToCenter(w, targetCount)].face == color) {
				targetCount++;
				if (targetCount >= 3)
					return;
			}
			while (centerFaces[sourceCount] != sourceFace) {
				sourceCount++;
				if (sourceCount >= 3)
					return;
			}
#ifdef DEBUG
			(void) printf("%d: face0=%d, position0=%d; face1=%d, position1=%d; face2=%d, position2=%d, targetCount %d, sourceCount %d\n",
				sourceFace, centerFaces[0], centerPositions[0],
				centerFaces[1], centerPositions[1],
				centerFaces[2], centerPositions[2],
				targetCount, sourceCount);
#endif
			if (centerFaces[sourceCount] == sourceFace) {
				sourcePosition = centerPositions[sourceCount];
				targetPosition = indexToCenter(w, targetCount);
				solve4To6Faces(w, sourcePosition, targetPosition);
			}
		} else if (centerFaces[count] == 3) {
			sourceFace = 3;
			while (w->oct.facetLoc[targetFace][indexToCenter(w, targetCount)].face == color) {
				targetCount++;
				if (targetCount >= 3)
					return;
			}
			while (centerFaces[sourceCount] != sourceFace) {
				sourceCount++;
				if (sourceCount >= 3)
					return;
			}
#ifdef DEBUG
			(void) printf("%d: face0=%d, position0=%d; face1=%d, position1=%d; face2=%d, position2=%d, targetCount %d, sourceCount %d\n",
				sourceFace, centerFaces[0], centerPositions[0],
				centerFaces[1], centerPositions[1],
				centerFaces[2], centerPositions[2],
				targetCount, sourceCount);
#endif
			if (centerFaces[sourceCount] == sourceFace) {
				sourcePosition = centerPositions[sourceCount];
				targetPosition = indexToCenter(w, targetCount);
				solve3To6Faces(w, sourcePosition, targetPosition);
			}
		} else if (centerFaces[count] == 1) {
			sourceFace = 1;
			while (w->oct.facetLoc[targetFace][indexToCenter(w, targetCount)].face == color) {
				targetCount++;
				if (targetCount >= 3)
					return;
			}
			while (centerFaces[sourceCount] != sourceFace) {
				sourceCount++;
				if (sourceCount >= 3)
					return;
			}
#ifdef DEBUG
			(void) printf("%d: face0=%d, position0=%d; face1=%d, position1=%d; face2=%d, position2=%d, targetCount %d, sourceCount %d\n",
				sourceFace, centerFaces[0], centerPositions[0],
				centerFaces[1], centerPositions[1],
				centerFaces[2], centerPositions[2],
				targetCount, sourceCount);
#endif
			if (centerFaces[sourceCount] == sourceFace) {
				sourcePosition = centerPositions[sourceCount];
				targetPosition = indexToCenter(w, targetCount);
				solve1To6Faces(w, sourcePosition, targetPosition);
			}
		}
	}
}

static void
solve4Faces(OctWidget w)
{
	int count;
	int sourcePosition, targetPosition;
	int sourceFace, targetFace = 4;
	int color = w->oct.facetLoc[targetFace][0].face;

#ifdef DEBUG
	(void) printf("targetFace %d\n", targetFace);
#endif
	for (count = 0; count < 3; count++) {
		int sourceCount = 0, targetCount = 0;

		findCenterPositionsRev(w, color);
#ifdef DEBUG
		(void) printf("face0=%d, position0=%d; face1=%d, position1=%d; face2=%d, position2=%d\n",
			centerFaces[0], centerPositions[0],
			centerFaces[1], centerPositions[1],
			centerFaces[2], centerPositions[2]);
#endif
		if (centerFaces[count] == 3) {
			sourceFace = 3;
			while (w->oct.facetLoc[targetFace][indexToCenter(w, targetCount)].face == color) {
				targetCount++;
				if (targetCount >= 3)
					return;
			}
			while (centerFaces[sourceCount] != sourceFace) {
				sourceCount++;
				if (sourceCount >= 3)
					return;
			}
#ifdef DEBUG
			(void) printf("%d: face0=%d, position0=%d; face1=%d, position1=%d; face2=%d, position2=%d, targetCount %d, sourceCount %d\n",
				sourceFace, centerFaces[0], centerPositions[0],
				centerFaces[1], centerPositions[1],
				centerFaces[2], centerPositions[2],
				targetCount, sourceCount);
#endif
			if (centerFaces[sourceCount] == sourceFace) {
				sourcePosition = centerPositions[sourceCount];
				targetPosition = indexToCenter(w, targetCount);
				solve3To4Faces(w, sourcePosition, targetPosition);
			}
		} else if (centerFaces[count] == 1) {
			sourceFace = 1;
			while (w->oct.facetLoc[targetFace][indexToCenter(w, targetCount)].face == color) {
				targetCount++;
				if (targetCount >= 3)
					return;
			}
			while (centerFaces[sourceCount] != sourceFace) {
				sourceCount++;
				if (sourceCount >= 3)
					return;
			}
#ifdef DEBUG
			(void) printf("%d: face0=%d, position0=%d; face1=%d, position1=%d; face2=%d, position2=%d, targetCount %d, sourceCount %d\n",
				sourceFace, centerFaces[0], centerPositions[0],
				centerFaces[1], centerPositions[1],
				centerFaces[2], centerPositions[2],
				targetCount, sourceCount);
#endif
			if (centerFaces[sourceCount] == sourceFace) {
				sourcePosition = centerPositions[sourceCount];
				targetPosition = indexToCenter(w, targetCount);
				solve1To4Faces(w, sourcePosition, targetPosition);
			}
		}
	}
}

static void
solve3Faces(OctWidget w)
{
	int count;
	int sourcePosition, targetPosition;
	int sourceFace, targetFace = 3;
	int color = w->oct.facetLoc[targetFace][0].face;

#ifdef DEBUG
	(void) printf("targetFace %d\n", targetFace);
#endif
	for (count = 0; count < 3; count++) {
		int sourceCount = 0, targetCount = 0;

		findCenterPositionsRev(w, color);
#ifdef DEBUG
		(void) printf("face0=%d, position0=%d; face1=%d, position1=%d; face2=%d, position2=%d\n",
			centerFaces[0], centerPositions[0],
			centerFaces[1], centerPositions[1],
			centerFaces[2], centerPositions[2]);
#endif
		if (centerFaces[count] == 1) {
			sourceFace = 1;
			while (w->oct.facetLoc[targetFace][indexToCenter(w, targetCount)].face == color) {
				targetCount++;
				if (targetCount >= 3)
					return;
			}
			while (centerFaces[sourceCount] != sourceFace) {
				sourceCount++;
				if (sourceCount >= 3)
					return;
			}
#ifdef DEBUG
			(void) printf("%d: face0=%d, position0=%d; face1=%d, position1=%d; face2=%d, position2=%d, targetCount %d, sourceCount %d\n",
				sourceFace, centerFaces[0], centerPositions[0],
				centerFaces[1], centerPositions[1],
				centerFaces[2], centerPositions[2],
				targetCount, sourceCount);
#endif
			if (centerFaces[sourceCount] == sourceFace) {
				sourcePosition = centerPositions[sourceCount];
				targetPosition = indexToCenter(w, targetCount);
				solve1To3Faces(w, sourcePosition, targetPosition);
			}
		}
	}
}

static void
swapOut0To2(OctWidget w, int targetPosition)
{
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	simpleCenterSwap(w, 4, LEFT, 1, BOTTOM);
	/* (0, 1):= (2, 1), (2, 2):= (0, 1), (2, 1):= (2, 2) */
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
}

static void
swapOut2To5(OctWidget w, int targetPosition)
{
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	simpleCenterSwap(w, 1, BOTTOM, 3, BOTTOM);
	/* (2, 1):= (5, 2), (5, 0):= (2, 1), (5, 2):= (5, 0) */
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
}

static void
swapOut5To7(OctWidget w, int targetPosition)
{
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	simpleCenterSwap(w, 3, BOTTOM, 0, RIGHT);
	/* (5, 2):= (7, 2), (7, 1):= (5, 2), (7, 2):= (7, 1) */
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
}

static void
swapOut6To4(OctWidget w, int targetPosition)
{
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	simpleCenterSwap(w, 2, LEFT, 7, TOP);
	/* (6, 1):= (4, 1), (4, 2):= (6, 1), (4, 1):= (4, 2) */
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
}

static void
swapOut4To3(OctWidget w, int targetPosition)
{
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	simpleCenterSwap(w, 7, TOP, 5, TOP);
	/* (4, 1):= (3, 2), (3, 0):= (4, 1), (3, 2):= (3, 0) */
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 2))
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
}

static void
swapOut3To1(OctWidget w, int targetPosition)
{
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	simpleCenterSwap(w, 5, TOP, 6, LEFT);
	/* (3, 2):= (1, 2), (1, 1):= (3, 2), (1, 2):= (1, 1) */
	if (targetPosition == indexToCenter(w, 0))
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	else if (targetPosition == indexToCenter(w, 1))
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
}

static void
solve0Orient(OctWidget w)
{
	int count, found = 0;
	int targetFace = 0;
	int faceRotation = w->oct.facetLoc[targetFace][0].rotation;

#ifdef DEBUG
	(void) printf("targetFace %d: %d\n", targetFace, faceRotation);
#endif
	for (count = 0; count < 3; count++) {
		centerPositions[found] = indexToCenter(w, count);
		centerRotations[found] = ((w->oct.facetLoc[targetFace][centerPositions[found]].rotation - faceRotation + 12) % 12) / 4;
		if (centerRotations[found] != 0) {
			found++;
		}
	}
	if (found == 0)
		return;
#ifdef DEBUG
	for (count = 0; count < found; count++) {
		(void) printf("%d count %d: centerPos %d, centerRot %d\n",
			targetFace, count, centerPositions[count], centerRotations[count]);
	}
	if (found == 2)
		(void) printf("solve0Orient: found=2, centerPos=%d\n",
			centerPositions[0]);
	else
		(void) printf("solve0Orient: found=3, centerRot=%d\n",
			centerRotations[0]);
#endif
	swapOut0To2(w, centerPositions[0]);
	if ((found == 2 && centerPositions[1] == indexToCenter(w, 1)) ||
			((found == 3) && centerRotations[0] == 1)) {
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		simpleCenterSwap(w, 4, LEFT, 3, BOTTOM);
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	} else if (found == 2 && centerPositions[1] == indexToCenter(w, 0)) {
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		simpleCenterSwap(w, 4, LEFT, 3, BOTTOM);
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	} else {
		simpleCenterSwap(w, 4, LEFT, 3, BOTTOM);
	}
	if (found == 2 && centerPositions[0] == indexToCenter(w, 0)) {
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		simpleCenterSwap(w, 4, RIGHT, 1, BOTTOM);
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	} else if ((found == 2 && centerPositions[0] == indexToCenter(w, 2)) ||
			((found == 3) && centerRotations[0] == 1)) {
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		simpleCenterSwap(w, 4, RIGHT, 1, BOTTOM);
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	} else {
		simpleCenterSwap(w, 4, RIGHT, 1, BOTTOM);
	}
	if (found == 3) {
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		simpleCenterSwap(w, 4, LEFT, 3, BOTTOM);
		movePuzzlePiece(w, 6, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	}
}

static void
solve2Orient(OctWidget w)
{
	int count, found = 0;
	int targetFace = 2;
	int faceRotation = w->oct.facetLoc[targetFace][0].rotation;

#ifdef DEBUG
	(void) printf("targetFace %d: %d\n", targetFace, faceRotation);
#endif
	for (count = 0; count < 3; count++) {
		centerPositions[found] = indexToCenter(w, count);
		centerRotations[found] = ((w->oct.facetLoc[targetFace][centerPositions[found]].rotation - faceRotation + 12) % 12) / 4;
		if (centerRotations[found] != 0) {
			found++;
		}
	}
	if (found == 0)
		return;
#ifdef DEBUG
	for (count = 0; count < found; count++) {
		(void) printf("%d count %d: centerPos %d, centerRot %d\n",
			targetFace, count, centerPositions[count], centerRotations[count]);
	}
	if (found == 2)
		(void) printf("solve2Orient: found=2, centerPos=%d\n",
			centerPositions[0]);
	else
		(void) printf("solve2Orient: found=3, centerRot=%d\n",
			centerRotations[0]);
#endif
	swapOut2To5(w, centerPositions[0]);
	if ((found == 2 && centerPositions[1] == indexToCenter(w, 2)) ||
			((found == 3) && centerRotations[0] == 2)) {
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		simpleCenterSwap(w, 1, BOTTOM, 5, BOTTOM);
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	} else if (found == 2 && centerPositions[1] == indexToCenter(w, 0)) {
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		simpleCenterSwap(w, 1, BOTTOM, 5, BOTTOM);
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	} else {
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		simpleCenterSwap(w, 1, BOTTOM, 5, BOTTOM);
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	}
	if (found == 2 && centerPositions[0] == indexToCenter(w, 0)) {
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		simpleCenterSwap(w, 1, TOP, 5, BOTTOM);
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	} else if ((found == 2 && centerPositions[0] == indexToCenter(w, 2)) ||
			((found == 3) && centerRotations[0] == 1)) {
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		simpleCenterSwap(w, 1, TOP, 5, BOTTOM);
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	} else {
		simpleCenterSwap(w, 1, TOP, 5, BOTTOM);
	}
	if (found == 3) {
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		simpleCenterSwap(w, 1, BOTTOM, 5, BOTTOM);
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	}
}

static void
solve5Orient(OctWidget w)
{
	int count, found = 0;
	int targetFace = 5;
	int faceRotation = w->oct.facetLoc[targetFace][0].rotation;

#ifdef DEBUG
	(void) printf("targetFace %d: %d\n", targetFace, faceRotation);
#endif
	for (count = 0; count < 3; count++) {
		centerPositions[found] = indexToCenter(w, count);
		centerRotations[found] = ((w->oct.facetLoc[targetFace][centerPositions[found]].rotation - faceRotation + 12) % 12) / 4;
		if (centerRotations[found] != 0) {
			found++;
		}
	}
	if (found == 0)
		return;
#ifdef DEBUG
	for (count = 0; count < found; count++) {
		(void) printf("%d count %d: centerPos %d, centerRot %d\n",
			targetFace, count, centerPositions[count], centerRotations[count]);
	}
	if (found == 2)
		(void) printf("solve5Orient: found=2, centerPos=%d\n",
			centerPositions[0]);
	else
		(void) printf("solve5Orient: found=3, centerRot=%d\n",
			centerRotations[0]);
#endif
	swapOut5To7(w, centerPositions[0]);
	if ((found == 2 && centerPositions[1] == indexToCenter(w, 1)) ||
			((found == 3) && centerRotations[0] == 1)) {
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		simpleCenterSwap(w, 3, BOTTOM, 4, LEFT);
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	} else if (found == 2 && centerPositions[1] == indexToCenter(w, 0)) {
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		simpleCenterSwap(w, 3, BOTTOM, 4, LEFT);
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	} else {
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		simpleCenterSwap(w, 3, BOTTOM, 4, LEFT);
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	}
	if ((found == 2 && centerPositions[0] == indexToCenter(w, 2)) ||
			((found == 3) && centerRotations[0] == 1)) {
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		simpleCenterSwap(w, 3, TOP, 6, LEFT);
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	} else if (found == 2 && centerPositions[0] == indexToCenter(w, 0)) {
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		simpleCenterSwap(w, 3, TOP, 6, LEFT);
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	} else {
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		simpleCenterSwap(w, 3, TOP, 6, LEFT);
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	}
	if (found == 3) {
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		simpleCenterSwap(w, 3, BOTTOM, 4, LEFT);
		movePuzzlePiece(w, 3, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	}
}

static void
solve7Orient(OctWidget w)
{
	int count, found = 0, i;
	int targetFace = 7;
	int faceRotation = w->oct.facetLoc[targetFace][0].rotation;

#ifdef DEBUG
	(void) printf("targetFace %d: %d\n", targetFace, faceRotation);
#endif
	for (count = 0; count < 3; count++) {
		centerPositions[found] = indexToCenter(w, count);
		centerRotations[found] = ((w->oct.facetLoc[targetFace][centerPositions[found]].rotation - faceRotation + 12) % 12) / 4;
		if (centerRotations[found] != 0) {
			found++;
		}
	}
	if (found == 0)
		return;
#ifdef DEBUG
	for (count = 0; count < found; count++) {
		(void) printf("%d count %d: centerPos %d, centerRot %d\n",
			targetFace, count, centerPositions[count], centerRotations[count]);
	}
	(void) printf("solve7Orient: found=3, centerRot=%d\n",
		centerRotations[0]);
#endif
	for (i = 0; i < centerRotations[0]; i++) {
		movePuzzlePiece(w, 7, indexToEdge(w, 0),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 5, indexToEdge(w, 0),
			BOTTOM, PERIOD3, False);
		swapOut5To7(w, centerPositions[0]);
		movePuzzlePiece(w, 5, indexToEdge(w, 0),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 4, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 7, indexToEdge(w, 0),
			BOTTOM, PERIOD3, False);
	}
}

static void
solve6Orient(OctWidget w)
{
	int count, found = 0;
	int targetFace = 6;
	int faceRotation = w->oct.facetLoc[targetFace][0].rotation;

#ifdef DEBUG
	(void) printf("targetFace %d: %d\n", targetFace, faceRotation);
#endif
	for (count = 0; count < 3; count++) {
		centerPositions[found] = indexToCenter(w, count);
		centerRotations[found] = ((w->oct.facetLoc[targetFace][centerPositions[found]].rotation - faceRotation + 12) % 12) / 4;
		if (centerRotations[found] != 0) {
			found++;
		}
	}
	if (found == 0)
		return;
#ifdef DEBUG
	for (count = 0; count < found; count++) {
		(void) printf("%d count %d: centerPos %d, centerRot %d\n",
			targetFace, count, centerPositions[count], centerRotations[count]);
	}
	if (found == 2)
		(void) printf("solve6Orient: found=2, centerPos=%d\n",
			centerPositions[0]);
	else
		(void) printf("solve6Orient: found=3, centerRot=%d\n",
			centerRotations[0]);
#endif
	swapOut6To4(w, centerPositions[0]);
	if ((found == 2 && centerPositions[1] == indexToCenter(w, 1)) ||
			((found == 3) && centerRotations[0] == 1)) {
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		simpleCenterSwap(w, 2, RIGHT, 5, TOP);
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	} else if (found == 2 && centerPositions[1] == indexToCenter(w, 0)) {
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		simpleCenterSwap(w, 2, RIGHT, 5, TOP);
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	} else {
		simpleCenterSwap(w, 2, RIGHT, 5, TOP);
	}
	if (found == 2 && centerPositions[0] == indexToCenter(w, 0)) {
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		simpleCenterSwap(w, 2, LEFT, 7, TOP);
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	} else if ((found == 2 && centerPositions[0] == indexToCenter(w, 2)) ||
			((found == 3) && centerRotations[0] == 1)) {
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		simpleCenterSwap(w, 2, LEFT, 7, TOP);
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	} else {
		simpleCenterSwap(w, 2, LEFT, 7, TOP);
	}
	if (found == 3) {
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		simpleCenterSwap(w, 2, RIGHT, 5, TOP);
		movePuzzlePiece(w, 0, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	}
}

static void
solve4Orient(OctWidget w)
{
	int count, found = 0;
	int targetFace = 4;
	int faceRotation = w->oct.facetLoc[targetFace][0].rotation;

#ifdef DEBUG
	(void) printf("targetFace %d: %d\n", targetFace, faceRotation);
#endif
	for (count = 0; count < 3; count++) {
		centerPositions[found] = indexToCenter(w, count);
		centerRotations[found] = ((w->oct.facetLoc[targetFace][centerPositions[found]].rotation - faceRotation + 12) % 12) / 4;
		if (centerRotations[found] != 0) {
			found++;
		}
	}
	if (found == 0)
		return;
#ifdef DEBUG
	for (count = 0; count < found; count++) {
		(void) printf("%d count %d: centerPos %d, centerRot %d\n",
			targetFace, count, centerPositions[count], centerRotations[count]);
	}
	if (found == 2)
		(void) printf("solve4Orient: found=2, centerPos=%d\n",
			centerPositions[0]);
	else
		(void) printf("solve4Orient: found=3, centerRot=%d\n",
			centerRotations[0]);
#endif
	swapOut4To3(w, centerPositions[0]);
	if ((found == 2 && centerPositions[1] == indexToCenter(w, 2)) ||
			((found == 3) && centerRotations[0] == 2)) {
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		simpleCenterSwap(w, 7, TOP, 3, TOP);
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	} else if (found == 2 && centerPositions[1] == indexToCenter(w, 0)) {
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		simpleCenterSwap(w, 7, TOP, 3, TOP);
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	} else {
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		simpleCenterSwap(w, 7, TOP, 3, TOP);
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	}
	if (found == 2 && centerPositions[0] == indexToCenter(w, 0)) {
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		simpleCenterSwap(w, 7, BOTTOM, 3, TOP);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	} else if ((found == 2 && centerPositions[0] == indexToCenter(w, 2)) ||
			((found == 3) && centerRotations[0] == 1)) {
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		simpleCenterSwap(w, 7, BOTTOM, 3, TOP);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
	} else {
		simpleCenterSwap(w, 7, BOTTOM, 3, TOP);
	}
	if (found == 3) {
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		simpleCenterSwap(w, 7, TOP, 3, TOP);
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
	}
}

static void
solve3Orient(OctWidget w)
{
	int count, found = 0;
	int targetFace = 3;
	int faceRotation = w->oct.facetLoc[targetFace][0].rotation;

#ifdef DEBUG
	(void) printf("targetFace %d: %d\n", targetFace, faceRotation);
#endif
	for (count = 0; count < 3; count++) {
		centerPositions[found] = indexToCenter(w, count);
		centerRotations[found] = ((w->oct.facetLoc[targetFace][centerPositions[found]].rotation - faceRotation + 12) % 12) / 4;
		if (centerRotations[found] != 0) {
			found++;
		}
	}
	if (found == 0)
		return;
#ifdef DEBUG
	for (count = 0; count < found; count++) {
		(void) printf("%d count %d: centerPos %d, centerRot %d\n",
			targetFace, count, centerPositions[count], centerRotations[count]);
	}
	if (found == 2)
		(void) printf("solve3Orient: found=2, centerPos=%d\n",
			centerPositions[0]);
	else
		(void) printf("solve3Orient: found=3, centerRot=%d\n",
			centerRotations[0]);
#endif
	swapOut3To1(w, centerPositions[0]);
	if ((found == 2 && centerPositions[1] == indexToCenter(w, 1)) ||
			((found == 3) && centerRotations[0] == 1)) {
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		simpleCenterSwap(w, 5, TOP, 2, RIGHT);
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	} else if (found == 2 && centerPositions[1] == indexToCenter(w, 0)) {
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		simpleCenterSwap(w, 5, TOP, 2, RIGHT);
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	} else {
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		simpleCenterSwap(w, 5, TOP, 2, RIGHT);
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	}
	if ((found == 2 && centerPositions[0] == indexToCenter(w, 2)) ||
			((found == 3) && centerRotations[0] == 1)) {
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		simpleCenterSwap(w, 5, BOTTOM, 0, RIGHT);
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	} else if (found == 2 && centerPositions[0] == indexToCenter(w, 0)) {
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		simpleCenterSwap(w, 5, BOTTOM, 0, RIGHT);
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
	} else {
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		simpleCenterSwap(w, 5, BOTTOM, 0, RIGHT);
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	}
	if (found == 3) {
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			BOTTOM, PERIOD3, False);
		simpleCenterSwap(w, 5, TOP, 2, RIGHT);
		movePuzzlePiece(w, 5, indexToEdge(w, 2),
			TOP, PERIOD3, False);
		movePuzzlePiece(w, 7, indexToEdge(w, 2),
			TOP, PERIOD3, False);
	}
}

static void
solve1Orient(OctWidget w)
{
	int count, found = 0, i;
	int targetFace = 1;
	int faceRotation = w->oct.facetLoc[targetFace][0].rotation;

#ifdef DEBUG
	(void) printf("targetFace %d: %d\n", targetFace, faceRotation);
#endif
	for (count = 0; count < 3; count++) {
		centerPositions[found] = indexToCenter(w, count);
		centerRotations[found] = ((w->oct.facetLoc[targetFace][centerPositions[found]].rotation - faceRotation + 12) % 12) / 4;
		if (centerRotations[found] != 0) {
			found++;
		}
	}
	if (found == 0)
		return;
#ifdef DEBUG
	for (count = 0; count < found; count++) {
		(void) printf("%d count %d: centerPos %d, centerRot %d\n",
			targetFace, count, centerPositions[count], centerRotations[count]);
	}
	(void) printf("solve1Orient: found=3, centerRot=%d\n",
		centerRotations[0]);
#endif
	for (i = 0; i < centerRotations[0]; i++) {
		movePuzzlePiece(w, 1, indexToEdge(w, 0),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			RIGHT, PERIOD3, False);
		movePuzzlePiece(w, 3, indexToEdge(w, 0),
			TOP, PERIOD3, False);
		swapOut3To1(w, centerPositions[0]);
		movePuzzlePiece(w, 3, indexToEdge(w, 0),
			BOTTOM, PERIOD3, False);
		movePuzzlePiece(w, 2, indexToEdge(w, 2),
			LEFT, PERIOD3, False);
		movePuzzlePiece(w, 1, indexToEdge(w, 0),
			TOP, PERIOD3, False);
	}
}

static void
solveCenterEarly(OctWidget w)
{
	int startFace = 0;
	int color = w->oct.facetLoc[startFace][0].face;
	int face = findPieceCenter(w, color, startFace);
	if (face == 2)
		movePuzzlePiece(w, 3, indexToEdge(w, 0),
			TOP, PERIOD3, False);
	else if (face == 5)
		movePuzzlePiece(w, 3, indexToEdge(w, 0),
			BOTTOM, PERIOD3, False);
	else if (face == 7)
		movePuzzlePiece(w, 1, indexToEdge(w, 0),
			BOTTOM, PERIOD3, False);
	startFace = 1;
	color = w->oct.facetLoc[startFace][0].face;
	face = findPieceCenter(w, color, startFace);
	if (face == 6)
		movePuzzlePiece(w, 2, indexToEdge(w, 0),
			LEFT, PERIOD3, False);
	else if (face == 3)
		movePuzzlePiece(w, 2, indexToEdge(w, 0),
			RIGHT, PERIOD3, False);
}

static void
solveCenter(OctWidget w)
{
	int i;
	int face0 = 0;
	int color0 = w->oct.facetLoc[face0][0].face;
	int face01 = findPieceCenter(w, color0, face0);
	int color01 = w->oct.facetLoc[face01][0].face;
	int face02 = findPieceCenter(w, color01, face01);
	int face2 = 2;
	int color2 = w->oct.facetLoc[face2][0].face;
	int face21 = findPieceCenter(w, color2, face2);
	int color21 = w->oct.facetLoc[face21][0].face;
	int face22 = findPieceCenter(w, color21, face21);
	int face1 = 1;
	int color1 = w->oct.facetLoc[face1][0].face;
	int face11 = findPieceCenter(w, color1, face1);
	int face3 = 3;
	int color3 = w->oct.facetLoc[face3][0].face;
	int face31 = findPieceCenter(w, color3, face3);
#ifdef DEBUG
	(void) printf("solve color0 %d, face01 %d, color01 %d, face02 %d\n",
		color0, face01, color01, face02);
	(void) printf("solve color2 %d, face21 %d, color21 %d, face22 %d\n",
		color0, face01, color21, face22);
#endif
	if (face0 == face01 && face0 == face02 && face2 == face22)
		return;
	else if (face0 == face02 && face2 == face22) {
		/* simple */
		if (face01 == 2) {
			for (i = 0; i < 3; i++) {
				movePuzzlePiece(w, 3, indexToEdge(w, 0),
					BOTTOM, PERIOD3, False);
				movePuzzlePiece(w, 1, indexToEdge(w, 0),
					BOTTOM, PERIOD3, False);
				movePuzzlePiece(w, 3, indexToEdge(w, 0),
					TOP, PERIOD3, False);
				movePuzzlePiece(w, 1, indexToEdge(w, 0),
					TOP, PERIOD3, False);
			}
		} else if (face01 == 5) {
			for (i = 0; i < 3; i++) {
				movePuzzlePiece(w, 3, indexToEdge(w, 0),
					BOTTOM, PERIOD3, False);
				movePuzzlePiece(w, 1, indexToEdge(w, 0),
					TOP, PERIOD3, False);
				movePuzzlePiece(w, 3, indexToEdge(w, 0),
					TOP, PERIOD3, False);
				movePuzzlePiece(w, 1, indexToEdge(w, 0),
					BOTTOM, PERIOD3, False);
			}
		} else if (face01 == 7) {
			for (i = 0; i < 3; i++) {
				movePuzzlePiece(w, 1, indexToEdge(w, 0),
					BOTTOM, PERIOD3, False);
				movePuzzlePiece(w, 3, indexToEdge(w, 0),
					TOP, PERIOD3, False);
				movePuzzlePiece(w, 1, indexToEdge(w, 0),
					TOP, PERIOD3, False);
				movePuzzlePiece(w, 3, indexToEdge(w, 0),
					BOTTOM, PERIOD3, False);
			}
		}
	} else {
		/* CMove */
		if (face0 == face01) {
			if (face11 == 3) {
				for (i = 0; i < 8; i++) {
					movePuzzlePiece(w, 1, indexToEdge(w, 0),
						TOP, PERIOD3, False);
					movePuzzlePiece(w, 0, indexToEdge(w, 0),
						LEFT, PERIOD3, False);
					movePuzzlePiece(w, 3, indexToEdge(w, 0),
						BOTTOM, PERIOD3, False);
				}
			} else {
				for (i = 0; i < 8; i++) {
					movePuzzlePiece(w, 3, indexToEdge(w, 1),
						TOP, PERIOD3, False);
					movePuzzlePiece(w, 0, indexToEdge(w, 1),
						RIGHT, PERIOD3, False);
					movePuzzlePiece(w, 1, indexToEdge(w, 1),
						BOTTOM, PERIOD3, False);
				}
			}
		} else if (face1 == face11) {
			if (face01 == 2) {
				for (i = 0; i < 8; i++) {
					movePuzzlePiece(w, 0, indexToEdge(w, 1),
						RIGHT, PERIOD3, False);
					movePuzzlePiece(w, 1, indexToEdge(w, 1),
						BOTTOM, PERIOD3, False);
					movePuzzlePiece(w, 2, indexToEdge(w, 1),
						LEFT, PERIOD3, False);
				}
			} else {
				for (i = 0; i < 8; i++) {
					movePuzzlePiece(w, 2, indexToEdge(w, 0),
						RIGHT, PERIOD3, False);
					movePuzzlePiece(w, 1, indexToEdge(w, 0),
						TOP, PERIOD3, False);
					movePuzzlePiece(w, 0, indexToEdge(w, 0),
						LEFT, PERIOD3, False);
				}
			}
		} else if (face2 == face21) {
			if (face31 == 1) {
				for (i = 0; i < 8; i++) {
					movePuzzlePiece(w, 3, indexToEdge(w, 0),
						BOTTOM, PERIOD3, False);
					movePuzzlePiece(w, 2, indexToEdge(w, 0),
						RIGHT, PERIOD3, False);
					movePuzzlePiece(w, 1, indexToEdge(w, 0),
						TOP, PERIOD3, False);
				}
			} else {
				for (i = 0; i < 8; i++) {
					movePuzzlePiece(w, 1, indexToEdge(w, 1),
						BOTTOM, PERIOD3, False);
					movePuzzlePiece(w, 2, indexToEdge(w, 1),
						LEFT, PERIOD3, False);
					movePuzzlePiece(w, 3, indexToEdge(w, 1),
						TOP, PERIOD3, False);
				}
			}
		} else if (face3 == face31) {
			if (face21 == 0) {
				for (i = 0; i < 8; i++) {
					movePuzzlePiece(w, 2, indexToEdge(w, 1),
						LEFT, PERIOD3, False);
					movePuzzlePiece(w, 3, indexToEdge(w, 1),
						TOP, PERIOD3, False);
					movePuzzlePiece(w, 0, indexToEdge(w, 1),
						RIGHT, PERIOD3, False);
				}
			} else {
				for (i = 0; i < 8; i++) {
					movePuzzlePiece(w, 0, indexToEdge(w, 0),
						LEFT, PERIOD3, False);
					movePuzzlePiece(w, 3, indexToEdge(w, 0),
						BOTTOM, PERIOD3, False);
					movePuzzlePiece(w, 2, indexToEdge(w, 0),
						RIGHT, PERIOD3, False);
				}
			}
		}
	}
}

static void
fixOrientCenterFace(OctWidget w, Boolean opp,
		int face0, int dir0, int face1, int dir1)
{
	int i, direction0, direction1;

	if (opp) {
		direction0 = dir0;
		direction1 = dir1;
	} else {
		direction0 = oppDir(dir0);
		direction1 = oppDir(dir1);
	}
	for (i = 0; i < 140; i++) {
		movePuzzlePiece(w, face0, indexToEdge(w, 2),
			direction0, PERIOD3, False);
		movePuzzlePiece(w, face1, indexToEdge(w, 2),
			direction1, PERIOD3, False);
	}
}

static int
totalPieceCenterOrient(OctWidget w)
{
	int position = exactCenter(w);
	int face, rotation, totalRotation = 0;

	for (face = 0; face < MAX_FACES; face++) {
		rotation = (w->oct.facetLoc[face][position].rotation
			- w->oct.facetLoc[face][0].rotation
			+ COORD + 1) % 3;
		totalRotation += rotation;
	}
	return totalRotation % 3;
}

static void
solveCenterOrient(OctWidget w)
{
	int face = 0;
	int value = findPieceCenterOrient(w, face);
	Boolean opp;

	if (value != 0) {
		opp = (value == 1);
#ifdef DEBUG
		(void) printf("solveCenterOrient %d %d\n", face, value);
#endif
		fixOrientCenterFace(w, opp, 6, RIGHT, 5, BOTTOM);
	}
	face = 1;
	value = findPieceCenterOrient(w, face);
	if (value != 0) {
		opp = (value == 1);
#ifdef DEBUG
		(void) printf("solveCenterOrient %d %d\n", face, value);
#endif
		fixOrientCenterFace(w, opp, 4, RIGHT, 5, TOP);
	}
	face = 3;
	value = findPieceCenterOrient(w, face);
	if (value != 0) {
		opp = (value == 1);
#ifdef DEBUG
		(void) printf("solveCenterOrient %d %d\n", face, value);
#endif
		fixOrientCenterFace(w, opp, 4, RIGHT, 7, BOTTOM);
	}
	face = 2;
	value = findPieceCenterOrient(w, face);
	if (value != 0) {
		opp = (value == 1);
#ifdef DEBUG
		(void) printf("solveCenterOrient %d %d\n", face, value);
#endif
		fixOrientCenterFace(w, opp, 2, LEFT, 4, LEFT);
	}
	face = 4;
	value = findPieceCenterOrient(w, face);
	if (value != 0) {
		opp = (value == 1);
#ifdef DEBUG
		(void) printf("solveCenterOrient %d %d\n", face, value);
#endif
		fixOrientCenterFace(w, opp, 2, RIGHT, 1, BOTTOM);
	}
	face = 5;
	value = findPieceCenterOrient(w, face);
	if (value != 0) {
		opp = (value == 1);
#ifdef DEBUG
		(void) printf("solveCenterOrient %d %d\n", face, value);
#endif
		fixOrientCenterFace(w, opp, 0, RIGHT, 1, TOP);
	}
	face = 7;
	value = findPieceCenterOrient(w, face);
	if (value != 0) {
		opp = (value == 1);
#ifdef DEBUG
		(void) printf("solveCenterOrient %d %d\n", face, value);
#endif
		fixOrientCenterFace(w, opp, 0, RIGHT, 3, BOTTOM);
	}
}


static void
mixup(OctWidget w, int rotation)
{
	int i, dir0 = LEFT, dir1 = BOTTOM;
	int face0 = 6, face1 = 5;

	if (rotation == 1) {
		dir0 = BOTTOM;
		dir1 = LEFT;
		face0 = 5;
		face1 = 6;
	}
	for (i = 0; i < 10; i++) {
		movePuzzlePiece(w, face0, indexToEdge(w, 2),
			dir0, PERIOD3, False);
		movePuzzlePiece(w, face1, indexToEdge(w, 2),
			dir1, PERIOD3, False);
	}
}

static void
solveFaces(OctWidget w)
{
	int rotation;

	solveTopCorners(w);
	solveBottomCorners(w);
	if (w->oct.size % 3 != 0) {
		if (w->oct.orient && w->oct.size > 2 && w->oct.size % 2 == 0) {
			solveCenterEarly(w);
			rotation = totalPieceCenterOrient(w);
#ifdef DEBUG
			(void) printf("rotation %d\n", rotation);
#endif
			if (rotation != 0) {
				mixup(w, rotation);
				solveTopCorners(w);
				solveBottomCorners(w);
				solveCenterEarly(w);
			}
		}
		solveTopEvenBottomOddCenters(w);
		solveTopOddBottomEvenCenters(w);
		if (w->oct.orient) {
			rotateTopHalf(w);
			rotateBottomHalf(w);
		}
	}
	if (w->oct.size > 2) {
		if (w->oct.sticky || w->oct.size % 2 != 0) {
			solveTopEdges(w);
			solveMiddleEdges(w);
			solveBottomEdges(w);
		}
		if (w->oct.size > 2 && w->oct.size % 2 == 0) {
			solveCenter(w);
		}
		solve0Faces(w);
		solve2Faces(w);
		solve5Faces(w);
		solve6Faces(w);
		solve4Faces(w);
		solve3Faces(w);
		if (w->oct.orient) {
			rotation = totalPieceCenterOrient(w);
			solve0Orient(w);
			solve2Orient(w);
			solve5Orient(w);
			solve7Orient(w);
			solve6Orient(w);
			solve4Orient(w);
			solve3Orient(w);
			solve1Orient(w);
			if (w->oct.size > 2 && w->oct.size % 2 == 0) {
#ifdef DEBUG
				rotation = totalPieceCenterOrient(w);
				(void) printf("totalRotation %d\n", rotation);
#endif
				solveCenterOrient(w);
			}
		}
	}
}

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