1 /*-
2 # X-BASED RUBIK'S CUBE(tm)
3 #
4 #  RubikU.c
5 #
6 ###
7 #
8 #  Copyright (c) 1994 - 99	David Albert Bagley, bagleyd@tux.org
9 #
10 #                   All Rights Reserved
11 #
12 #  Permission to use, copy, modify, and distribute this software and
13 #  its documentation for any purpose and without fee is hereby granted,
14 #  provided that the above copyright notice appear in all copies and
15 #  that both that copyright notice and this permission notice appear in
16 #  supporting documentation, and that the name of the author not be
17 #  used in advertising or publicity pertaining to distribution of the
18 #  software without specific, written prior permission.
19 #
20 #  This program is distributed in the hope that it will be "playable",
21 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
22 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23 #
24 */
25 
26 /* Undo algorithm */
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <X11/IntrinsicP.h>
31 #include <X11/Intrinsic.h>
32 #include <X11/StringDefs.h>
33 #include <X11/CoreP.h>
34 #include "RubikP.h"
35 #include "Rubik2dP.h"
36 #include "Rubik3dP.h"
37 
38 typedef struct _MoveRecord {
39 #if 0
40 	int         face, direction, control;
41 #endif
42 	unsigned short int packed;	/* This makes assumptions on the data. */
43 	int         position;	/* Do not make assumptions on this one. */
44 } MoveRecord;
45 
46 typedef struct _MoveStack {
47 	MoveRecord  move;
48 	struct _MoveStack *previous, *next;
49 } MoveStack;
50 
51 static MoveStack *currMove, *lastMove, *firstMove;
52 static int  count;
53 RubikLoc   *startLoc[MAXFACES] =
54 {
55 	NULL, NULL, NULL, NULL, NULL, NULL
56 };
57 
58 static void InitStack(void);
59 static void PushStack(MoveRecord move);
60 static void PopStack(MoveRecord * move);
61 static int  EmptyStack(void);
62 static void FlushStack(void);
63 
64 static void
InitStack(void)65 InitStack(void)
66 {
67 	if (!(lastMove = (MoveStack *) malloc(sizeof (MoveStack))))
68 		XtError("Not enough memory, exiting.");
69 	if (!(firstMove = (MoveStack *) malloc(sizeof (MoveStack))))
70 		XtError("Not enough memory, exiting.");
71 	firstMove->previous = lastMove->next = NULL;
72 	firstMove->next = lastMove;
73 	lastMove->previous = firstMove;
74 	count = 0;
75 }
76 
77 static void
PushStack(MoveRecord move)78 PushStack(MoveRecord move)
79 {
80 	if (!(currMove = (MoveStack *) malloc(sizeof (MoveStack))))
81 		XtError("Not enough memory, exiting.");
82 	lastMove->previous->next = currMove;
83 	currMove->previous = lastMove->previous;
84 	currMove->next = lastMove;
85 	lastMove->previous = currMove;
86 	currMove->move = move;
87 	count++;
88 }
89 
90 static void
PopStack(MoveRecord * move)91 PopStack(MoveRecord * move)
92 {
93 	*move = lastMove->previous->move;
94 	currMove = lastMove->previous;
95 	lastMove->previous->previous->next = lastMove;
96 	lastMove->previous = lastMove->previous->previous;
97 	(void) free((void *) currMove);
98 	count--;
99 }
100 
101 static int
EmptyStack(void)102 EmptyStack(void)
103 {
104 	return (lastMove->previous == firstMove);
105 }
106 
107 static void
FlushStack(void)108 FlushStack(void)
109 {
110 	while (lastMove->previous != firstMove) {
111 		currMove = lastMove->previous;
112 		lastMove->previous->previous->next = lastMove;
113 		lastMove->previous = lastMove->previous->previous;
114 		(void) free((void *) currMove);
115 	}
116 	count = 0;
117 }
118 
119 /**********************************/
120 
121 void
InitMoves(void)122 InitMoves(void)
123 {
124 	InitStack();
125 }
126 
127 static void
WriteMove(MoveRecord * move,int face,int position,int direction,int control)128 WriteMove(MoveRecord * move, int face, int position, int direction, int control)
129 {
130 #if 0
131 	move->face = face;
132 	move->direction = direction;
133 	move->control = control;
134 #endif
135 	move->packed = ((control & 0xF) << 8) + ((direction & 0xF) << 4) +
136 		(face & 0xF);
137 	move->position = position;
138 }
139 
140 static void
ReadMove(int * face,int * position,int * direction,int * control,MoveRecord move)141 ReadMove(int *face, int *position, int *direction, int *control, MoveRecord move)
142 {
143 #if 0
144 	*face = move.face;
145 	*direction = move.direction;
146 	*control = move.control;
147 #endif
148 	*face = (int) (move.packed & 0xF);
149 	*direction = (int) ((move.packed >> 4) & 0xF);
150 	*control = (int) ((move.packed >> 8) & 0xF);
151 	*position = move.position;
152 }
153 
154 void
PutMove(int face,int position,int direction,int control)155 PutMove(int face, int position, int direction, int control)
156 {
157 	MoveRecord  move;
158 
159 	WriteMove(&move, face, position, direction, control);
160 	PushStack(move);
161 }
162 
163 void
GetMove(int * face,int * position,int * direction,int * control)164 GetMove(int *face, int *position, int *direction, int *control)
165 {
166 	MoveRecord  move;
167 
168 	PopStack(&move);
169 	ReadMove(face, position, direction, control, move);
170 }
171 
172 int
MadeMoves(void)173 MadeMoves(void)
174 {
175 	return !EmptyStack();
176 }
177 
178 void
FlushMoves(RubikWidget w)179 FlushMoves(RubikWidget w)
180 {
181 	int         face, position;
182 
183 	FlushStack();
184 	for (face = 0; face < MAXFACES; face++)
185 		for (position = 0; position < sizeFace(w, face); position++) {
186 			startLoc[face][position].face =
187 				w->rubik.cubeLoc[face][position].face;
188 			startLoc[face][position].rotation =
189 				w->rubik.cubeLoc[face][position].rotation;
190 		}
191 }
192 
193 int
NumMoves(void)194 NumMoves(void)
195 {
196 	return count;
197 }
198 
199 void
ScanMoves(FILE * fp,RubikWidget w,int moves)200 ScanMoves(FILE * fp, RubikWidget w, int moves)
201 {
202 	int         face, position, direction, control, k;
203 	char        c;
204 
205 	for (k = 0; k < moves; k++) {
206 		while ((c = getc(fp)) != EOF && c != SYMBOL);
207 		(void) fscanf(fp, "%d %d %d %d", &face, &position, &direction, &control);
208 		MoveRubik(w, face, position, direction, control);
209 	}
210 }
211 
212 void
PrintMoves(FILE * fp)213 PrintMoves(FILE * fp)
214 {
215 	int         face, position, direction, control, counter = 0;
216 
217 	currMove = firstMove->next;
218 	(void) fprintf(fp, "moves\tface\tpos\tdir\tcon\n");
219 	while (currMove != lastMove) {
220 		ReadMove(&face, &position, &direction, &control, currMove->move);
221 		(void) fprintf(fp, "%d%c\t%d\t%d\t%d\t%d\n",
222 		      ++counter, SYMBOL, face, position, direction, control);
223 		currMove = currMove->next;
224 	}
225 }
226 
227 void
ScanStartPosition(FILE * fp,RubikWidget w)228 ScanStartPosition(FILE * fp, RubikWidget w)
229 {
230 	int         face, position, num;
231 	char        c;
232 
233 	while ((c = getc(fp)) != EOF && c != SYMBOL);
234 	for (face = 0; face < MAXFACES; face++)
235 		for (position = 0; position < sizeFace(w, face); position++) {
236 			(void) fscanf(fp, "%d ", &num);
237 			startLoc[face][position].face = num;
238 			if (w->rubik.orient) {
239 				(void) fscanf(fp, "%d ", &num);
240 				startLoc[face][position].rotation = num;
241 			}
242 		}
243 }
244 
245 void
PrintStartPosition(FILE * fp,RubikWidget w)246 PrintStartPosition(FILE * fp, RubikWidget w)
247 {
248 	int         face, position;
249 
250 	(void) fprintf(fp, "\nstartingPosition%c\n", SYMBOL);
251 	for (face = 0; face < MAXFACES; face++) {
252 		for (position = 0; position < sizeFace(w, face); position++) {
253 			(void) fprintf(fp, "%d ", startLoc[face][position].face);
254 			if (w->rubik.orient)
255 				(void) fprintf(fp, "%d  ", startLoc[face][position].rotation);
256 		}
257 		(void) fprintf(fp, "\n");
258 	}
259 }
260 
261 void
SetStartPosition(RubikWidget w)262 SetStartPosition(RubikWidget w)
263 {
264 	int         face, position;
265 
266 	for (face = 0; face < MAXFACES; face++)
267 		for (position = 0; position < sizeFace(w, face); position++) {
268 			w->rubik.cubeLoc[face][position].face =
269 				startLoc[face][position].face;
270 			if (w->rubik.orient)
271 				w->rubik.cubeLoc[face][position].rotation =
272 					startLoc[face][position].rotation;
273 		}
274 	DrawAllPolyhedrons(w);
275 }
276