1 /* $Id: pathfile.c,v 1.3 1998/04/30 05:11:56 mrogre Exp $ */
2 /* Copyright (c) 1998 Joe Rumsey (mrogre@mediaone.net) */
3 #include "copyright.h"
4 #include <config.h>
5
6
7 #include <stdio.h>
8 #include <string.h>
9 #ifdef HAVE_STRINGS_H
10 # include <strings.h>
11 #endif
12 #include <sys/stat.h>
13 #include <ctype.h>
14 #include <stdlib.h>
15
16 #include "struct.h"
17 #include "paths.h"
18 #include "pathfile.h"
19 #include "data.h"
20 #include "defs.h"
21
22 #define MAXFILENAME 1024
23
24 #define MAXPATHLEN 50
25 #define MAXLINE 1024
26
27 typedef enum {
28 PF_PATHDEF,
29 PF_PATHS,
30 PF_SHAPES,
31 PF_DELAYS
32 } PathfileToken;
33
34 struct path_entry
35 {
36 int dir, duration;
37 };
38
39 struct path_info
40 {
41 int startx, starty, len;
42 };
43
44 struct path_entry epaths[NUMPATHS][MAXPATHLEN];
45 struct path_info pathinfo[NUMPATHS];
46
47 int al_shapes[MAXALIENS];
48 int al_delays[MAXALIENS];
49 int al_paths[MAXALIENS];
50
51 int
get_line(FILE * file,char * buf)52 get_line(FILE* file, char* buf)
53 {
54 int done = 0;
55 char nextline[MAXLINE];
56
57 buf[0] = 0;
58 while(!done)
59 {
60 if(!fgets(nextline, MAXLINE, file))
61 return 0;
62
63 /* remove newline */
64 nextline[strlen(nextline) - 1] = 0;
65
66 if(strlen(nextline) + strlen(buf) >= MAXLINE) {
67 fprintf(stderr, "get_line: Line too long\n");
68 return -1;
69 }
70
71 strcpy(buf + strlen(buf), nextline);
72
73 if(nextline[strlen(nextline) -1] != '\\')
74 done = 1;
75 else {
76 buf[strlen(buf) -1] = ' ';
77 }
78 }
79 return 1;
80 }
81
82 PathfileToken
get_token(char * line,int * elem,char ** data)83 get_token(char* line, int* elem, char** data)
84 {
85 PathfileToken pt;
86 char *datastart;
87
88 *elem = -1;
89
90 if(strncmp(line, "paths:", 6) == 0) {
91 pt = PF_PATHS;
92 } else if (strncmp(line, "path.", 5) == 0) {
93 if(line[5] >= '0' && line[5] <= '9')
94 *elem = line[5] - '0';
95 else if(line[5] >= 'a' && line[5] <= 'z')
96 *elem = line[5] - 'a' + 10;
97 else if(line[5] >= 'A' && line[5] <= 'Z')
98 *elem = line[5] - 'A' + 36;
99 else {
100 fprintf(stderr, "%c is not a valid path identifier\n", line[5]);
101 return -1;
102 }
103 pt = PF_PATHDEF;
104 } else if (strncmp(line, "delays:", 7) == 0) {
105 pt = PF_DELAYS;
106 } else if (strncmp(line, "shapes:", 7) == 0) {
107 pt = PF_SHAPES;
108 } else {
109 return -1;
110 }
111
112 datastart = strchr(line, ':');
113 if(!datastart)
114 return -1;
115 datastart++;
116
117 while(isspace(*datastart))
118 datastart++;
119
120 if(!(*datastart))
121 return -1;
122
123 *data = datastart;
124 return pt;
125
126 }
127
128 #define iscompass(c) (((c) == 'n') || ((c) == 'e') || ((c) == 's') || ((c) == 'w'))
129 #define CHKDIR(x) \
130 curdir++; if(strcmp(x, dir) == 0) { gotdir = curdir; }
131
132 static void
parse_path(int pnum,char * pstr)133 parse_path(int pnum, char* pstr)
134 {
135 char *fnd;
136 char dir[40];
137 int dp;
138 int curdir = -1, gotdir;
139 int duration;
140 int curentry;
141 int sx, sy;
142 char *comma;
143
144 curentry = 0;
145
146 comma = strchr(pstr, ',');
147 sx = atoi(pstr);
148 sy = atoi(comma+1);
149 fnd = strchr(pstr, ':');
150 while(!iscompass(*fnd) && *fnd)
151 fnd++;
152
153 if(!(*fnd))
154 fprintf(stderr, "No path info for path %d\n", pnum);
155
156 while(*fnd) {
157 dp = 0;
158 while(iscompass(*fnd) && dp < 3) {
159 dir[dp] = *fnd;
160 fnd++;
161 dp++;
162 }
163 if(!isdigit(*fnd)) {
164 fprintf(stderr, "Error parsing path: %s\n", pstr);
165 return;
166 }
167 dir[dp] = 0;
168 curdir = -1;
169 gotdir = -1;
170
171 CHKDIR("n");
172 CHKDIR("nne");
173 CHKDIR("ne");
174 CHKDIR("ene");
175 CHKDIR("e");
176 CHKDIR("ese");
177 CHKDIR("se");
178 CHKDIR("sse");
179 CHKDIR("s");
180 CHKDIR("ssw");
181 CHKDIR("sw");
182 CHKDIR("wsw");
183 CHKDIR("w");
184 CHKDIR("wnw");
185 CHKDIR("nw");
186 CHKDIR("nnw");
187
188 if(gotdir < 0) {
189 fprintf(stderr, "direction %s in path %d is not valid\n",
190 dir, pnum);
191 }
192
193 duration = atoi(fnd);
194
195 epaths[pnum][curentry].dir = gotdir;
196 epaths[pnum][curentry].duration = duration;
197 curentry++;
198 while(isdigit(*fnd) || isspace(*fnd))
199 fnd++;
200 }
201 epaths[pnum][curentry].dir = -1;
202 epaths[pnum][curentry].duration = -1;
203
204 pathinfo[pnum].len = curentry;
205 pathinfo[pnum].startx = sx;
206 pathinfo[pnum].starty = sy;
207 }
208
209 static int
parse_shapes(char * data)210 parse_shapes(char* data)
211 {
212 char* chk;
213 int i;
214
215 for(i = 0, chk = data; i < MAXALIENS; i++)
216 {
217 while(isspace(*chk)) chk++;
218 if(!(*chk))
219 return 0;
220
221 if(*chk >= '0' && *chk <= '9')
222 al_shapes[i] = *chk - '0';
223 else if(*chk >= 'a' && *chk <= 'z')
224 al_shapes[i] = *chk - 'a' + 10;
225 else if(*chk >= 'A' && *chk <= 'Z')
226 al_shapes[i] = *chk - 'A' + 10 + 26;
227 else if(*chk == '-')
228 al_shapes[i] = -1;
229 else {
230 fprintf(stderr, "'%c' is not a valid shape character\n", *chk);
231 al_shapes[i] = 0;
232 }
233
234 chk++;
235 }
236
237 return 1;
238 }
239
240 static int
parse_paths(char * data)241 parse_paths(char* data)
242 {
243 char* chk;
244 int i;
245
246 for(i = 0, chk = data; i < MAXALIENS; i++)
247 {
248 while(isspace(*chk)) chk++;
249 if(!(*chk))
250 return 0;
251
252 if(*chk >= '0' && *chk <= '9')
253 al_paths[i] = *chk - '0';
254 else if(*chk >= 'a' && *chk <= 'z')
255 al_paths[i] = *chk - 'a' + 10;
256 else if(*chk >= 'A' && *chk <= 'Z')
257 al_paths[i] = *chk - 'A' + 10 + 26;
258 else if(*chk == '-')
259 al_paths[i] = -1;
260 else {
261 fprintf(stderr, "'%c' is not a valid shape character\n", *chk);
262 al_paths[i] = 0;
263 }
264
265 chk++;
266 }
267
268 return 1;
269 }
270
271 static int
parse_delays(char * data)272 parse_delays(char* data)
273 {
274 char* chk;
275 int i;
276
277 for(i = 0, chk = data; i < MAXALIENS; i++)
278 {
279 while(isspace(*chk)) chk++;
280 if(!(*chk))
281 return 0;
282
283 al_delays[i] = atoi(chk);
284 while(!isspace(*chk) && *chk) chk++;
285 }
286
287 return 1;
288 }
289
290 int
read_level(int lev)291 read_level(int lev)
292 {
293 char filename[MAXFILENAME];
294 char readline[MAXLINE];
295 char *data;
296 int gotPaths = 0, gotShapes = 0, gotDelays = 0;
297 int rlen;
298 int elem;
299 FILE* lf;
300 PathfileToken tok;
301 static int maxLevel = 1;
302 static char *real_level_path = 0;
303 struct stat statbuf;
304
305 if(!real_level_path)
306 {
307 sprintf(filename, "%s", LEVELDIR);
308 if(stat(filename, &statbuf) != 0 || !(statbuf.st_mode & S_IFDIR)) {
309 sprintf(filename, "./levels");
310 if(stat(filename, &statbuf) != 0 || !(statbuf.st_mode & S_IFDIR)) {
311 fprintf(stderr, "Can't find level directory %s OR ./levels\n",
312 XGALAGADIR);
313 return -1;
314 }
315 }
316 real_level_path = malloc(strlen(filename) + 1);
317 strcpy(real_level_path, filename);
318 }
319
320 sprintf(filename, "%s/level%d.xgl", real_level_path, lev);
321 lf = fopen(filename, "r");
322 if(!lf) {
323 /* Dont use recursion, to avoid stack overflow if start level is
324 * very high (or the game is played for a _very_ long time. :-)
325 * -- JEH */
326 for (lev = lev - maxLevel; lev > 0 && ! lf ;lev = lev - maxLevel) {
327 metaLevel++;
328 /* real_level_path is already set, so.. */
329 sprintf(filename, "%s/level%d.xgl", real_level_path, lev);
330 lf = fopen(filename, "r");
331 }
332
333 //fprintf(stderr, "Can't open level file %s\n", filename);
334 //return read_level(lev - maxLevel);
335 }
336
337 if(lev > maxLevel)
338 maxLevel = lev;
339
340 while(!feof(lf)) {
341 if((rlen = get_line(lf, readline)) <= 0) {
342 if(gotShapes && gotPaths && gotDelays) {
343 return 1;
344 }
345 fprintf(stderr, "Error reading level file %s:\n", filename);
346 if(!gotShapes)
347 fprintf(stderr, " Missing shapes\n");
348 if(!gotPaths)
349 fprintf(stderr, " Missing paths\n");
350 if(!gotDelays)
351 fprintf(stderr, " Missing delays\n");
352
353 fclose(lf);
354 return 0;
355 }
356
357 switch((tok = get_token(readline, &elem, &data))) {
358 case PF_PATHDEF:
359 parse_path(elem, data);
360 break;
361 case PF_SHAPES:
362 gotShapes = parse_shapes(data);
363 break;
364 case PF_PATHS:
365 gotPaths = parse_paths(data);
366 break;
367 case PF_DELAYS:
368 gotDelays = parse_delays(data);
369 break;
370 default:
371 break;
372 }
373 }
374
375 fclose(lf);
376
377 if(gotShapes && gotPaths && gotDelays) {
378 return 1;
379 }
380
381 return 0;
382 }
383
get_path(int anum)384 int get_path(int anum)
385 {
386 return al_paths[anum];
387 }
388
get_xy(int anum,int * x,int * y)389 void get_xy(int anum, int* x, int* y)
390 {
391 *x = (WINWIDTH * pathinfo[al_paths[anum]].startx) / 400;
392 *y = (WINHEIGHT * pathinfo[al_paths[anum]].starty) / 500;
393 }
394
get_delay(int anum)395 int get_delay(int anum)
396 {
397 return al_delays[anum];
398 }
399
get_dir(int pnum,int pos)400 int get_dir(int pnum, int pos)
401 {
402 return epaths[pnum][pos].dir;
403 }
404
get_duration(int pnum,int pos)405 int get_duration(int pnum, int pos)
406 {
407 return epaths[pnum][pos].duration;
408 }
409
get_shape(int anum)410 int get_shape(int anum)
411 {
412 return al_shapes[anum];
413 }
414