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