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