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