1 
2 /*-
3 # X-BASED HEXAGONS
4 #
5 #  HexagonsU.c
6 #
7 ###
8 #
9 #  Copyright (c) 1994 - 99	David Albert Bagley, bagleyd@tux.org
10 #
11 #                   All Rights Reserved
12 #
13 #  Permission to use, copy, modify, and distribute this software and
14 #  its documentation for any purpose and without fee is hereby granted,
15 #  provided that the above copyright notice appear in all copies and
16 #  that both that copyright notice and this permission notice appear in
17 #  supporting documentation, and that the name of the author not be
18 #  used in advertising or publicity pertaining to distribution of the
19 #  software without specific, written prior permission.
20 #
21 #  This program is distributed in the hope that it will be "playable",
22 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
23 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
24 #
25 */
26 
27 /* Undo algorithm */
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <X11/IntrinsicP.h>
32 #include <X11/Intrinsic.h>
33 #include <X11/StringDefs.h>
34 #include <X11/CoreP.h>
35 #include "HexagonsP.h"
36 
37 typedef struct _MoveRecord {
38 #if 0
39 	int         direction;
40 #endif
41 	unsigned char packed;	/* This makes assumptions on the data. */
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 static int  startSpace[SPACES];
52 static int  startRow[ROWTYPES];
53 int        *startPosition = NULL;
54 
55 static void InitStack(void);
56 static void PushStack(MoveRecord move);
57 static void PopStack(MoveRecord * move);
58 static int  EmptyStack(void);
59 static void FlushStack(void);
60 
61 static void
InitStack(void)62 InitStack(void)
63 {
64 	if (!(lastMove = (MoveStack *) malloc(sizeof (MoveStack))))
65 		XtError("Not enough memory, exiting.");
66 	if (!(firstMove = (MoveStack *) malloc(sizeof (MoveStack))))
67 		XtError("Not enough memory, exiting.");
68 	firstMove->previous = lastMove->next = NULL;
69 	firstMove->next = lastMove;
70 	lastMove->previous = firstMove;
71 	count = 0;
72 }
73 
74 static void
PushStack(MoveRecord move)75 PushStack(MoveRecord move)
76 {
77 	if (!(currMove = (MoveStack *) malloc(sizeof (MoveStack))))
78 		XtError("Not enough memory, exiting.");
79 	lastMove->previous->next = currMove;
80 	currMove->previous = lastMove->previous;
81 	currMove->next = lastMove;
82 	lastMove->previous = currMove;
83 	currMove->move = move;
84 	count++;
85 }
86 
87 static void
PopStack(MoveRecord * move)88 PopStack(MoveRecord * move)
89 {
90 	*move = lastMove->previous->move;
91 	currMove = lastMove->previous;
92 	lastMove->previous->previous->next = lastMove;
93 	lastMove->previous = lastMove->previous->previous;
94 	(void) free((void *) currMove);
95 	count--;
96 }
97 
98 static int
EmptyStack(void)99 EmptyStack(void)
100 {
101 	return (lastMove->previous == firstMove);
102 }
103 
104 static void
FlushStack(void)105 FlushStack(void)
106 {
107 	while (lastMove->previous != firstMove) {
108 		currMove = lastMove->previous;
109 		lastMove->previous->previous->next = lastMove;
110 		lastMove->previous = lastMove->previous->previous;
111 		(void) free((void *) currMove);
112 	}
113 	count = 0;
114 }
115 
116 /**********************************/
117 
118 void
InitMoves(void)119 InitMoves(void)
120 {
121 	InitStack();
122 }
123 
124 static void
WriteMove(MoveRecord * move,int direction)125 WriteMove(MoveRecord * move, int direction)
126 {
127 #if 0
128 	move->direction = direction;
129 #endif
130 	move->packed = direction & 0xF;
131 }
132 
133 static void
ReadMove(int * direction,MoveRecord move)134 ReadMove(int *direction, MoveRecord move)
135 {
136 #if 0
137 	*direction = move.direction;
138 #endif
139 	*direction = (int) (move.packed & 0xF);
140 }
141 
142 void
PutMove(int direction)143 PutMove(int direction)
144 {
145 	MoveRecord  move;
146 
147 	WriteMove(&move, direction);
148 	PushStack(move);
149 }
150 
151 void
GetMove(int * direction)152 GetMove(int *direction)
153 {
154 	MoveRecord  move;
155 
156 	PopStack(&move);
157 	ReadMove(direction, move);
158 }
159 
160 int
MadeMoves(void)161 MadeMoves(void)
162 {
163 	return !EmptyStack();
164 }
165 
166 void
FlushMoves(HexagonsWidget w)167 FlushMoves(HexagonsWidget w)
168 {
169 	int         i;
170 
171 	FlushStack();
172 	startSpace[LOW] = w->hexagons.spacePosition[LOW];
173 	startSpace[HIGH] = w->hexagons.spacePosition[HIGH];
174 	startRow[TRBL] = w->hexagons.spaceRow[TRBL];
175 	startRow[TLBR] = w->hexagons.spaceRow[TLBR];
176 	startRow[ROW] = w->hexagons.spaceRow[ROW];
177 	for (i = 0; i < w->hexagons.sizeSize; i++)
178 		startPosition[i] = w->hexagons.tileOfPosition[i];
179 }
180 
181 int
NumMoves(void)182 NumMoves(void)
183 {
184 	return count;
185 }
186 
187 void
ScanMoves(FILE * fp,HexagonsWidget w,int moves)188 ScanMoves(FILE * fp, HexagonsWidget w, int moves)
189 {
190 	int         direction, l;
191 	char        c;
192 
193 	for (l = 0; l < moves; l++) {
194 		while ((c = getc(fp)) != EOF && c != SYMBOL);
195 		(void) fscanf(fp, "%d", &direction);
196 		if (!MoveHexagonsDir(w, direction))
197 			(void) fprintf(fp, "%d move in direction %d, can not be made.",
198 				       l, direction);
199 	}
200 }
201 
202 void
PrintMoves(FILE * fp)203 PrintMoves(FILE * fp)
204 {
205 	int         direction, counter = 0;
206 
207 	currMove = firstMove->next;
208 	(void) fprintf(fp, "moves\tdir\n");
209 	while (currMove != lastMove) {
210 		ReadMove(&direction, currMove->move);
211 		(void) fprintf(fp, "%d%c\t%d\n", ++counter, SYMBOL, direction);
212 		currMove = currMove->next;
213 	}
214 }
215 
216 void
ScanStartPosition(FILE * fp,HexagonsWidget w)217 ScanStartPosition(FILE * fp, HexagonsWidget w)
218 {
219 	int         i, num;
220 	char        c;
221 
222 	while ((c = getc(fp)) != EOF && c != SYMBOL);
223 	for (i = 0; i < w->hexagons.sizeSize; i++) {
224 		(void) fscanf(fp, "%d ", &num);
225 		startPosition[i] = num;
226 		if (!num)
227 			startSpace[HIGH] = i;
228 		else if (num == -1)
229 			startSpace[LOW] = i;
230 	}
231 	if (w->hexagons.corners) {
232 		startRow[HIGH] = Row(w, startSpace[HIGH]);
233 		if (w->hexagons.size > 1)
234 			startRow[LOW] = Row(w, startSpace[LOW]);
235 	} else {
236 		startRow[ROW] = Row(w, startSpace[HIGH]);
237 		startRow[TRBL] = TrBl(w, startSpace[HIGH], startRow[ROW]);
238 		startRow[TLBR] = TlBr(w, startSpace[HIGH], startRow[ROW]);
239 	}
240 }
241 
242 void
PrintStartPosition(FILE * fp,HexagonsWidget w)243 PrintStartPosition(FILE * fp, HexagonsWidget w)
244 {
245 	int         rowPos = 0, r = 0, rp, p, length = 0;
246 
247 	(void) fprintf(fp, "\nstartingPosition%c\n", SYMBOL);
248 	for (p = 0; p < w->hexagons.sizeSize; p++) {
249 		if (rowPos == 0) {
250 			if (p < w->hexagons.sizeSize / 2) {	/* CENTER */
251 				length = w->hexagons.size + r;
252 				for (rp = 0; rp < w->hexagons.size - 1 - r; rp++)
253 					(void) fprintf(fp, "  ");
254 			} else {
255 				length = 3 * w->hexagons.size - r - 2;
256 				for (rp = 0; rp < r - w->hexagons.size + 1; rp++)
257 					(void) fprintf(fp, "  ");
258 			}
259 		}
260 		(void) fprintf(fp, "%3d ", startPosition[p]);
261 		if (rowPos == length - 1) {
262 			r++;
263 			rowPos = 0;
264 			(void) fprintf(fp, "\n");
265 		} else
266 			rowPos++;
267 	}
268 	(void) fprintf(fp, "\n");
269 }
270 
271 void
SetStartPosition(HexagonsWidget w)272 SetStartPosition(HexagonsWidget w)
273 {
274 	int         i;
275 
276 	w->hexagons.spacePosition[HIGH] = startSpace[HIGH];
277 	w->hexagons.spacePosition[LOW] = startSpace[LOW];
278 	w->hexagons.spaceRow[TRBL] = startRow[TRBL];
279 	w->hexagons.spaceRow[TLBR] = startRow[TLBR];
280 	w->hexagons.spaceRow[ROW] = startRow[ROW];
281 	for (i = 0; i < w->hexagons.sizeSize; i++)
282 		w->hexagons.tileOfPosition[i] = startPosition[i];
283 	DrawAllTiles(w);
284 }
285