eobish

view src/level.c @ 4:ce0548d24918

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