eobish

annotate src/level.c @ 7:6a350c554e46

started DOS port
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 19 Jan 2015 15:49:14 +0200
parents ce0548d24918
children
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