eobish
diff src/level.c @ 4:ce0548d24918
mostly works
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 18 Jan 2015 13:30:30 +0200 (2015-01-18) |
parents | |
children | 6a350c554e46 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/level.c Sun Jan 18 13:30:30 2015 +0200 1.3 @@ -0,0 +1,138 @@ 1.4 +#include <stdio.h> 1.5 +#include <stdlib.h> 1.6 +#include <string.h> 1.7 +#include <ctype.h> 1.8 +#include <math.h> 1.9 +#include "level.h" 1.10 + 1.11 +#define C_WALL '#' 1.12 +#define C_START 's' 1.13 +#define C_GOAL 'x' 1.14 + 1.15 +#define IS_SOLID(x) ((x) == C_WALL) 1.16 + 1.17 +static void clean_line(char *buf); 1.18 + 1.19 + 1.20 +void level_init(struct level *lvl) 1.21 +{ 1.22 + memset(lvl, 0, sizeof *lvl); 1.23 +} 1.24 + 1.25 +void level_destroy(struct level *lvl) 1.26 +{ 1.27 + if(lvl) { 1.28 + destroy_tileset(&lvl->tileset); 1.29 + } 1.30 +} 1.31 + 1.32 +int level_load(struct level *lvl, const char *fname) 1.33 +{ 1.34 + FILE *fp; 1.35 + char buf[256], *dir, *slash; 1.36 + int i, size[2], nlines; 1.37 + 1.38 + dir = alloca(strlen(fname) + 1); 1.39 + strcpy(dir, fname); 1.40 + if((slash = strrchr(dir, '/'))) { 1.41 + slash[1] = 0; 1.42 + } else { 1.43 + *dir = 0; 1.44 + } 1.45 + 1.46 + if(!(fp = fopen(fname, "r"))) { 1.47 + fprintf(stderr, "failed to open file: %s\n", fname); 1.48 + return -1; 1.49 + } 1.50 + 1.51 + nlines = 0; 1.52 + while(fgets(buf, sizeof buf, fp)) { 1.53 + clean_line(buf); 1.54 + 1.55 + if(memcmp(buf, "@s", 2) == 0) { 1.56 + if(sscanf(buf, "@s %dx%d", size, size + 1) != 2) { 1.57 + fprintf(stderr, "level file %s doesn't start with size definition\n", fname); 1.58 + fclose(fp); 1.59 + return -1; 1.60 + } 1.61 + if(size[0] > MAX_LEVEL_SIZE || size[1] > MAX_LEVEL_SIZE) { 1.62 + fprintf(stderr, "level size %dx%d is larger than compile-time maximum (%d)\n", size[0], size[1], MAX_LEVEL_SIZE); 1.63 + fclose(fp); 1.64 + return -1; 1.65 + } 1.66 + 1.67 + lvl->num_cells[0] = size[0]; 1.68 + lvl->num_cells[1] = size[1]; 1.69 + continue; 1.70 + 1.71 + } else if(memcmp(buf, "@t", 2) == 0) { 1.72 + char *path, *tname = buf + 3; 1.73 + 1.74 + while(*tname && isspace(*tname)) ++tname; 1.75 + 1.76 + path = alloca(strlen(tname) + strlen(dir) + 2); 1.77 + sprintf(path, "%s%s", dir, tname); 1.78 + 1.79 + if(load_tileset(&lvl->tileset, path) == -1) { 1.80 + fprintf(stderr, "failed to load tileset for level %s\n", fname); 1.81 + fclose(fp); 1.82 + return -1; 1.83 + } 1.84 + continue; 1.85 + } 1.86 + 1.87 + if(nlines >= size[0]) { 1.88 + fprintf(stderr, "warning: level contains more lines than specified, ignoring the rest\n"); 1.89 + break; 1.90 + } 1.91 + 1.92 + for(i=0; buf[i]; i++) { 1.93 + if(i >= size[1]) { 1.94 + fprintf(stderr, "warning: line %d is longer than the level size definition says. Skipping the rest.\n", nlines + 1); 1.95 + break; 1.96 + } 1.97 + lvl->cells[nlines][i] = buf[i]; 1.98 + 1.99 + if(buf[i] == C_START) { 1.100 + lvl->start_pos[0] = i; 1.101 + lvl->start_pos[1] = nlines; 1.102 + printf("start cell found (%d,%d)\n", lvl->start_pos[0], lvl->start_pos[1]); 1.103 + } 1.104 + if(buf[i] == C_GOAL) { 1.105 + lvl->goal_pos[0] = i; 1.106 + lvl->goal_pos[1] = nlines; 1.107 + printf("gold cell found (%d, %d)\n", i, nlines); 1.108 + } 1.109 + } 1.110 + nlines++; 1.111 + } 1.112 + 1.113 + fclose(fp); 1.114 + return 0; 1.115 +} 1.116 + 1.117 +static int clamp(int x, int low, int high) 1.118 +{ 1.119 + return x < low ? low : (x > high ? high : x); 1.120 +} 1.121 + 1.122 +int level_cell(struct level *lvl, int cx, int cy) 1.123 +{ 1.124 + cx = clamp(cx, 0, lvl->num_cells[1] - 1); 1.125 + cy = clamp(cy, 0, lvl->num_cells[0] - 1); 1.126 + 1.127 + return lvl->cells[cy][cx]; 1.128 +} 1.129 + 1.130 + 1.131 +static void clean_line(char *buf) 1.132 +{ 1.133 + char *end = buf + strlen(buf) - 1; 1.134 + 1.135 + if(end <= buf) return; 1.136 + 1.137 + while(end >= buf && !isprint(*end)) { 1.138 + *end-- = 0; 1.139 + } 1.140 +} 1.141 +