rev |
line source |
nuclear@4
|
1 #include <stdio.h>
|
nuclear@4
|
2 #include <stdlib.h>
|
nuclear@4
|
3 #include <string.h>
|
nuclear@4
|
4 #include <ctype.h>
|
nuclear@4
|
5 #include <math.h>
|
nuclear@7
|
6 #if defined(_MSC_VER) || defined(__WATCOMC__)
|
nuclear@7
|
7 #include <malloc.h>
|
nuclear@7
|
8 #else
|
nuclear@7
|
9 #include <alloca.h>
|
nuclear@7
|
10 #endif
|
nuclear@4
|
11 #include "level.h"
|
nuclear@4
|
12
|
nuclear@4
|
13 #define C_WALL '#'
|
nuclear@4
|
14 #define C_START 's'
|
nuclear@4
|
15 #define C_GOAL 'x'
|
nuclear@4
|
16
|
nuclear@4
|
17 #define IS_SOLID(x) ((x) == C_WALL)
|
nuclear@4
|
18
|
nuclear@4
|
19 static void clean_line(char *buf);
|
nuclear@4
|
20
|
nuclear@4
|
21
|
nuclear@4
|
22 void level_init(struct level *lvl)
|
nuclear@4
|
23 {
|
nuclear@4
|
24 memset(lvl, 0, sizeof *lvl);
|
nuclear@4
|
25 }
|
nuclear@4
|
26
|
nuclear@4
|
27 void level_destroy(struct level *lvl)
|
nuclear@4
|
28 {
|
nuclear@4
|
29 if(lvl) {
|
nuclear@4
|
30 destroy_tileset(&lvl->tileset);
|
nuclear@4
|
31 }
|
nuclear@4
|
32 }
|
nuclear@4
|
33
|
nuclear@4
|
34 int level_load(struct level *lvl, const char *fname)
|
nuclear@4
|
35 {
|
nuclear@4
|
36 FILE *fp;
|
nuclear@4
|
37 char buf[256], *dir, *slash;
|
nuclear@4
|
38 int i, size[2], nlines;
|
nuclear@4
|
39
|
nuclear@4
|
40 dir = alloca(strlen(fname) + 1);
|
nuclear@4
|
41 strcpy(dir, fname);
|
nuclear@4
|
42 if((slash = strrchr(dir, '/'))) {
|
nuclear@4
|
43 slash[1] = 0;
|
nuclear@4
|
44 } else {
|
nuclear@4
|
45 *dir = 0;
|
nuclear@4
|
46 }
|
nuclear@4
|
47
|
nuclear@4
|
48 if(!(fp = fopen(fname, "r"))) {
|
nuclear@4
|
49 fprintf(stderr, "failed to open file: %s\n", fname);
|
nuclear@4
|
50 return -1;
|
nuclear@4
|
51 }
|
nuclear@4
|
52
|
nuclear@4
|
53 nlines = 0;
|
nuclear@4
|
54 while(fgets(buf, sizeof buf, fp)) {
|
nuclear@4
|
55 clean_line(buf);
|
nuclear@4
|
56
|
nuclear@4
|
57 if(memcmp(buf, "@s", 2) == 0) {
|
nuclear@4
|
58 if(sscanf(buf, "@s %dx%d", size, size + 1) != 2) {
|
nuclear@4
|
59 fprintf(stderr, "level file %s doesn't start with size definition\n", fname);
|
nuclear@4
|
60 fclose(fp);
|
nuclear@4
|
61 return -1;
|
nuclear@4
|
62 }
|
nuclear@4
|
63 if(size[0] > MAX_LEVEL_SIZE || size[1] > MAX_LEVEL_SIZE) {
|
nuclear@4
|
64 fprintf(stderr, "level size %dx%d is larger than compile-time maximum (%d)\n", size[0], size[1], MAX_LEVEL_SIZE);
|
nuclear@4
|
65 fclose(fp);
|
nuclear@4
|
66 return -1;
|
nuclear@4
|
67 }
|
nuclear@4
|
68
|
nuclear@4
|
69 lvl->num_cells[0] = size[0];
|
nuclear@4
|
70 lvl->num_cells[1] = size[1];
|
nuclear@4
|
71 continue;
|
nuclear@4
|
72
|
nuclear@4
|
73 } else if(memcmp(buf, "@t", 2) == 0) {
|
nuclear@4
|
74 char *path, *tname = buf + 3;
|
nuclear@4
|
75
|
nuclear@4
|
76 while(*tname && isspace(*tname)) ++tname;
|
nuclear@4
|
77
|
nuclear@4
|
78 path = alloca(strlen(tname) + strlen(dir) + 2);
|
nuclear@4
|
79 sprintf(path, "%s%s", dir, tname);
|
nuclear@4
|
80
|
nuclear@4
|
81 if(load_tileset(&lvl->tileset, path) == -1) {
|
nuclear@4
|
82 fprintf(stderr, "failed to load tileset for level %s\n", fname);
|
nuclear@4
|
83 fclose(fp);
|
nuclear@4
|
84 return -1;
|
nuclear@4
|
85 }
|
nuclear@4
|
86 continue;
|
nuclear@4
|
87 }
|
nuclear@4
|
88
|
nuclear@4
|
89 if(nlines >= size[0]) {
|
nuclear@4
|
90 fprintf(stderr, "warning: level contains more lines than specified, ignoring the rest\n");
|
nuclear@4
|
91 break;
|
nuclear@4
|
92 }
|
nuclear@4
|
93
|
nuclear@4
|
94 for(i=0; buf[i]; i++) {
|
nuclear@4
|
95 if(i >= size[1]) {
|
nuclear@4
|
96 fprintf(stderr, "warning: line %d is longer than the level size definition says. Skipping the rest.\n", nlines + 1);
|
nuclear@4
|
97 break;
|
nuclear@4
|
98 }
|
nuclear@4
|
99 lvl->cells[nlines][i] = buf[i];
|
nuclear@4
|
100
|
nuclear@4
|
101 if(buf[i] == C_START) {
|
nuclear@4
|
102 lvl->start_pos[0] = i;
|
nuclear@4
|
103 lvl->start_pos[1] = nlines;
|
nuclear@4
|
104 printf("start cell found (%d,%d)\n", lvl->start_pos[0], lvl->start_pos[1]);
|
nuclear@4
|
105 }
|
nuclear@4
|
106 if(buf[i] == C_GOAL) {
|
nuclear@4
|
107 lvl->goal_pos[0] = i;
|
nuclear@4
|
108 lvl->goal_pos[1] = nlines;
|
nuclear@4
|
109 printf("gold cell found (%d, %d)\n", i, nlines);
|
nuclear@4
|
110 }
|
nuclear@4
|
111 }
|
nuclear@4
|
112 nlines++;
|
nuclear@4
|
113 }
|
nuclear@4
|
114
|
nuclear@4
|
115 fclose(fp);
|
nuclear@4
|
116 return 0;
|
nuclear@4
|
117 }
|
nuclear@4
|
118
|
nuclear@4
|
119 static int clamp(int x, int low, int high)
|
nuclear@4
|
120 {
|
nuclear@4
|
121 return x < low ? low : (x > high ? high : x);
|
nuclear@4
|
122 }
|
nuclear@4
|
123
|
nuclear@4
|
124 int level_cell(struct level *lvl, int cx, int cy)
|
nuclear@4
|
125 {
|
nuclear@4
|
126 cx = clamp(cx, 0, lvl->num_cells[1] - 1);
|
nuclear@4
|
127 cy = clamp(cy, 0, lvl->num_cells[0] - 1);
|
nuclear@4
|
128
|
nuclear@4
|
129 return lvl->cells[cy][cx];
|
nuclear@4
|
130 }
|
nuclear@4
|
131
|
nuclear@4
|
132
|
nuclear@4
|
133 static void clean_line(char *buf)
|
nuclear@4
|
134 {
|
nuclear@4
|
135 char *end = buf + strlen(buf) - 1;
|
nuclear@4
|
136
|
nuclear@4
|
137 if(end <= buf) return;
|
nuclear@4
|
138
|
nuclear@4
|
139 while(end >= buf && !isprint(*end)) {
|
nuclear@4
|
140 *end-- = 0;
|
nuclear@4
|
141 }
|
nuclear@4
|
142 }
|
nuclear@4
|
143
|