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