nuclear@4: #include nuclear@4: #include nuclear@4: #include nuclear@4: #include nuclear@4: #include nuclear@7: #if defined(_MSC_VER) || defined(__WATCOMC__) nuclear@7: #include nuclear@7: #else nuclear@7: #include nuclear@7: #endif nuclear@4: #include "level.h" nuclear@4: nuclear@4: #define C_WALL '#' nuclear@4: #define C_START 's' nuclear@4: #define C_GOAL 'x' nuclear@4: nuclear@4: #define IS_SOLID(x) ((x) == C_WALL) nuclear@4: nuclear@4: static void clean_line(char *buf); nuclear@4: nuclear@4: nuclear@4: void level_init(struct level *lvl) nuclear@4: { nuclear@4: memset(lvl, 0, sizeof *lvl); nuclear@4: } nuclear@4: nuclear@4: void level_destroy(struct level *lvl) nuclear@4: { nuclear@4: if(lvl) { nuclear@4: destroy_tileset(&lvl->tileset); nuclear@4: } nuclear@4: } nuclear@4: nuclear@4: int level_load(struct level *lvl, const char *fname) nuclear@4: { nuclear@4: FILE *fp; nuclear@4: char buf[256], *dir, *slash; nuclear@4: int i, size[2], nlines; nuclear@4: nuclear@4: dir = alloca(strlen(fname) + 1); nuclear@4: strcpy(dir, fname); nuclear@4: if((slash = strrchr(dir, '/'))) { nuclear@4: slash[1] = 0; nuclear@4: } else { nuclear@4: *dir = 0; nuclear@4: } nuclear@4: nuclear@4: if(!(fp = fopen(fname, "r"))) { nuclear@4: fprintf(stderr, "failed to open file: %s\n", fname); nuclear@4: return -1; nuclear@4: } nuclear@4: nuclear@4: nlines = 0; nuclear@4: while(fgets(buf, sizeof buf, fp)) { nuclear@4: clean_line(buf); nuclear@4: nuclear@4: if(memcmp(buf, "@s", 2) == 0) { nuclear@4: if(sscanf(buf, "@s %dx%d", size, size + 1) != 2) { nuclear@4: fprintf(stderr, "level file %s doesn't start with size definition\n", fname); nuclear@4: fclose(fp); nuclear@4: return -1; nuclear@4: } nuclear@4: if(size[0] > MAX_LEVEL_SIZE || size[1] > MAX_LEVEL_SIZE) { nuclear@4: fprintf(stderr, "level size %dx%d is larger than compile-time maximum (%d)\n", size[0], size[1], MAX_LEVEL_SIZE); nuclear@4: fclose(fp); nuclear@4: return -1; nuclear@4: } nuclear@4: nuclear@4: lvl->num_cells[0] = size[0]; nuclear@4: lvl->num_cells[1] = size[1]; nuclear@4: continue; nuclear@4: nuclear@4: } else if(memcmp(buf, "@t", 2) == 0) { nuclear@4: char *path, *tname = buf + 3; nuclear@4: nuclear@4: while(*tname && isspace(*tname)) ++tname; nuclear@4: nuclear@4: path = alloca(strlen(tname) + strlen(dir) + 2); nuclear@4: sprintf(path, "%s%s", dir, tname); nuclear@4: nuclear@4: if(load_tileset(&lvl->tileset, path) == -1) { nuclear@4: fprintf(stderr, "failed to load tileset for level %s\n", fname); nuclear@4: fclose(fp); nuclear@4: return -1; nuclear@4: } nuclear@4: continue; nuclear@4: } nuclear@4: nuclear@4: if(nlines >= size[0]) { nuclear@4: fprintf(stderr, "warning: level contains more lines than specified, ignoring the rest\n"); nuclear@4: break; nuclear@4: } nuclear@4: nuclear@4: for(i=0; buf[i]; i++) { nuclear@4: if(i >= size[1]) { nuclear@4: fprintf(stderr, "warning: line %d is longer than the level size definition says. Skipping the rest.\n", nlines + 1); nuclear@4: break; nuclear@4: } nuclear@4: lvl->cells[nlines][i] = buf[i]; nuclear@4: nuclear@4: if(buf[i] == C_START) { nuclear@4: lvl->start_pos[0] = i; nuclear@4: lvl->start_pos[1] = nlines; nuclear@4: printf("start cell found (%d,%d)\n", lvl->start_pos[0], lvl->start_pos[1]); nuclear@4: } nuclear@4: if(buf[i] == C_GOAL) { nuclear@4: lvl->goal_pos[0] = i; nuclear@4: lvl->goal_pos[1] = nlines; nuclear@4: printf("gold cell found (%d, %d)\n", i, nlines); nuclear@4: } nuclear@4: } nuclear@4: nlines++; nuclear@4: } nuclear@4: nuclear@4: fclose(fp); nuclear@4: return 0; nuclear@4: } nuclear@4: nuclear@4: static int clamp(int x, int low, int high) nuclear@4: { nuclear@4: return x < low ? low : (x > high ? high : x); nuclear@4: } nuclear@4: nuclear@4: int level_cell(struct level *lvl, int cx, int cy) nuclear@4: { nuclear@4: cx = clamp(cx, 0, lvl->num_cells[1] - 1); nuclear@4: cy = clamp(cy, 0, lvl->num_cells[0] - 1); nuclear@4: nuclear@4: return lvl->cells[cy][cx]; nuclear@4: } nuclear@4: nuclear@4: nuclear@4: static void clean_line(char *buf) nuclear@4: { nuclear@4: char *end = buf + strlen(buf) - 1; nuclear@4: nuclear@4: if(end <= buf) return; nuclear@4: nuclear@4: while(end >= buf && !isprint(*end)) { nuclear@4: *end-- = 0; nuclear@4: } nuclear@4: } nuclear@4: