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