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