1 /*-
2 # X-BASED DINOSAUR CUBE
3 #
4 #  DinoU.c
5 #
6 ###
7 #
8 #  Copyright (c) 1995 - 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 "DinoP.h"
35 #include "Dino2dP.h"
36 #include "Dino3dP.h"
37 
38 typedef struct _MoveRecord {
39 #if 0
40 	int         face, position, direction, style, control;
41 #endif
42 	unsigned long int packed;	/* This makes assumptions on the data. */
43 } MoveRecord;
44 
45 typedef struct _MoveStack {
46 	MoveRecord  move;
47 	struct _MoveStack *previous, *next;
48 } MoveStack;
49 
50 static MoveStack *currMove, *lastMove, *firstMove;
51 static int  count;
52 static DinoCornerLoc startLoc[MAXFACES][MAXORIENT];
53 
54 static void InitStack(void);
55 static void PushStack(MoveRecord move);
56 static void PopStack(MoveRecord * move);
57 static int  EmptyStack(void);
58 static void FlushStack(void);
59 
60 static void
InitStack(void)61 InitStack(void)
62 {
63 	if (!(lastMove = (MoveStack *) malloc(sizeof (MoveStack))))
64 		XtError("Not enough memory, exiting.");
65 	if (!(firstMove = (MoveStack *) malloc(sizeof (MoveStack))))
66 		XtError("Not enough memory, exiting.");
67 	firstMove->previous = lastMove->next = NULL;
68 	firstMove->next = lastMove;
69 	lastMove->previous = firstMove;
70 	count = 0;
71 }
72 
73 static void
PushStack(MoveRecord move)74 PushStack(MoveRecord move)
75 {
76 	if (!(currMove = (MoveStack *) malloc(sizeof (MoveStack))))
77 		XtError("Not enough memory, exiting.");
78 	lastMove->previous->next = currMove;
79 	currMove->previous = lastMove->previous;
80 	currMove->next = lastMove;
81 	lastMove->previous = currMove;
82 	currMove->move = move;
83 	count++;
84 }
85 
86 static void
PopStack(MoveRecord * move)87 PopStack(MoveRecord * move)
88 {
89 	*move = lastMove->previous->move;
90 	currMove = lastMove->previous;
91 	lastMove->previous->previous->next = lastMove;
92 	lastMove->previous = lastMove->previous->previous;
93 	(void) free((void *) currMove);
94 	count--;
95 }
96 
97 static int
EmptyStack(void)98 EmptyStack(void)
99 {
100 	return (lastMove->previous == firstMove);
101 }
102 
103 static void
FlushStack(void)104 FlushStack(void)
105 {
106 	while (lastMove->previous != firstMove) {
107 		currMove = lastMove->previous;
108 		lastMove->previous->previous->next = lastMove;
109 		lastMove->previous = lastMove->previous->previous;
110 		(void) free((void *) currMove);
111 	}
112 	count = 0;
113 }
114 
115 /**********************************/
116 
117 void
InitMoves(void)118 InitMoves(void)
119 {
120 	InitStack();
121 }
122 
123 static void
WriteMove(MoveRecord * move,int face,int position,int direction,int style,int control)124 WriteMove(MoveRecord * move, int face, int position, int direction, int style, int control)
125 {
126 #if 0
127 	move->face = face;
128 	moves->position = position;
129 	move->direction = direction;
130 	move->style = style;
131 	move->control = control;
132 #endif
133 	move->packed = ((control & 0xF) << 16) + ((style & 0xF) << 12) +
134 		((direction & 0xF) << 8) + ((position & 0xF) << 4) + (face & 0xF);
135 }
136 
137 static void
ReadMove(int * face,int * position,int * direction,int * style,int * control,MoveRecord move)138 ReadMove(int *face, int *position, int *direction, int *style, int *control, MoveRecord move)
139 {
140 #if 0
141 	*face = move.face;
142 	*position = move.position;
143 	*direction = move.direction;
144 	*style = move.style;
145 	*control = move.control;
146 #endif
147 	*face = (int) (move.packed & 0xF);
148 	*position = (int) ((move.packed >> 4) & 0xF);
149 	*direction = (int) ((move.packed >> 8) & 0xF);
150 	*style = (int) ((move.packed >> 12) & 0xF);
151 	*control = (int) ((move.packed >> 16) & 0xF);
152 }
153 
154 void
PutMove(int face,int position,int direction,int style,int control)155 PutMove(int face, int position, int direction, int style, int control)
156 {
157 	MoveRecord  move;
158 
159 	WriteMove(&move, face, position, direction, style, control);
160 	PushStack(move);
161 }
162 
163 void
GetMove(int * face,int * position,int * direction,int * style,int * control)164 GetMove(int *face, int *position, int *direction, int *style, int *control)
165 {
166 	MoveRecord  move;
167 
168 	PopStack(&move);
169 	ReadMove(face, position, direction, style, control, move);
170 }
171 
172 int
MadeMoves(void)173 MadeMoves(void)
174 {
175 	return !EmptyStack();
176 }
177 
178 void
FlushMoves(DinoWidget w)179 FlushMoves(DinoWidget w)
180 {
181 	int         face, position;
182 
183 	FlushStack();
184 	for (face = 0; face < MAXFACES; face++)
185 		for (position = 0; position < MAXORIENT; position++) {
186 			startLoc[face][position].face = w->dino.cubeLoc[face][position].face;
187 			startLoc[face][position].rotation =
188 				w->dino.cubeLoc[face][position].rotation;
189 		}
190 }
191 
192 int
NumMoves(void)193 NumMoves(void)
194 {
195 	return count;
196 }
197 
198 void
ScanMoves(FILE * fp,DinoWidget w,int moves)199 ScanMoves(FILE * fp, DinoWidget w, int moves)
200 {
201 	int         face, position, direction, style, control, k;
202 	char        c;
203 
204 	for (k = 0; k < moves; k++) {
205 		while ((c = getc(fp)) != EOF && c != SYMBOL);
206 		(void) fscanf(fp, "%d %d %d %d %d", &face, &position, &direction,
207 			      &style, &control);
208 		MoveDino(w, face, position, direction, style, control);
209 	}
210 }
211 
212 void
PrintMoves(FILE * fp)213 PrintMoves(FILE * fp)
214 {
215 	int         face, position, direction, style, control, counter = 0;
216 
217 	currMove = firstMove->next;
218 	(void) fprintf(fp, "moves\tface\tpos\tdir\tstyle\tcon\n");
219 	while (currMove != lastMove) {
220 		ReadMove(&face, &position, &direction, &style, &control, currMove->move);
221 		(void) fprintf(fp, "%d%c\t%d\t%d\t%d\t%d\t%d\n",
222 		++counter, SYMBOL, face, position, direction, style, control);
223 		currMove = currMove->next;
224 	}
225 }
226 
227 void
ScanStartPosition(FILE * fp,DinoWidget w)228 ScanStartPosition(FILE * fp, DinoWidget 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 < MAXORIENT; position++) {
236 			(void) fscanf(fp, "%d ", &num);
237 			startLoc[face][position].face = num;
238 			if (w->dino.orient) {
239 				(void) fscanf(fp, "%d ", &num);
240 				startLoc[face][position].rotation = num;
241 			}
242 		}
243 }
244 
245 void
PrintStartPosition(FILE * fp,DinoWidget w)246 PrintStartPosition(FILE * fp, DinoWidget 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 < MAXORIENT; position++) {
253 			(void) fprintf(fp, "%d ", startLoc[face][position].face);
254 			if (w->dino.orient)
255 				(void) fprintf(fp, "%d  ", startLoc[face][position].rotation);
256 		}
257 		(void) fprintf(fp, "\n");
258 	}
259 }
260 
261 void
SetStartPosition(DinoWidget w)262 SetStartPosition(DinoWidget w)
263 {
264 	int         face, position;
265 
266 	for (face = 0; face < MAXFACES; face++)
267 		for (position = 0; position < MAXORIENT; position++) {
268 			w->dino.cubeLoc[face][position].face = startLoc[face][position].face;
269 			if (w->dino.orient)
270 				w->dino.cubeLoc[face][position].rotation =
271 					startLoc[face][position].rotation;
272 		}
273 	DrawAllPolyhedrons(w);
274 }
275