X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=tools%2Fdunger%2Fsrc%2Flevel.c;h=3a1a9bf9349d6c95fcaf89a2e1081de5083b6271;hb=8d36df2b04dfa5d747dd21ae2ddf7d349524674a;hp=582592422bacaa4da6ff863c4548042063495c72;hpb=576f9aa6409354c392d2ff661d61dbf6d967a8f8;p=vrlugburz diff --git a/tools/dunger/src/level.c b/tools/dunger/src/level.c index 5825924..3a1a9bf 100644 --- a/tools/dunger/src/level.c +++ b/tools/dunger/src/level.c @@ -1,27 +1,143 @@ #include #include #include +#include +#include #include "level.h" -struct level *create_level(int xsz, int ysz) +int init_level(struct level *lvl, int xsz, int ysz) { - struct level *lvl; - - if(!(lvl = malloc(sizeof *lvl))) { - return 0; - } if(!(lvl->cells = calloc(xsz * ysz, sizeof *lvl->cells))) { free(lvl); - return 0; + return -1; } lvl->width = xsz; lvl->height = ysz; - return lvl; + return 0; } -void free_level(struct level *lvl) +void destroy_level(struct level *lvl) { if(!lvl) return; free(lvl->cells); - free(lvl); +} + +int load_level(struct level *lvl, const char *fname) +{ + FILE *fp; + struct ts_node *ts, *node, *iter; + int sz, cx, cy; + struct cell *cell; + + if(!(fp = fopen(fname, "rb"))) { + return -1; + } + + if(!(ts = ts_load(fname))) { + fprintf(stderr, "failed to load level: %s\n", fname); + return -1; + } + if(strcmp(ts->name, "dunged_level") != 0) { + fprintf(stderr, "invalid or corrupted level file: %s\n", fname); + ts_free_tree(ts); + return -1; + } + + if((sz = ts_get_attr_int(ts, "size", 0)) <= 0) { + sz = 32; + } + + if(init_level(lvl, sz, sz) == -1) { + fprintf(stderr, "failed to initialize a %dx%d level\n", sz, sz); + ts_free_tree(ts); + return -1; + } + + iter = ts->child_list; + while(iter) { + node = iter; + iter = iter->next; + + if(strcmp(node->name, "cell") == 0) { + cx = ts_get_attr_int(node, "x", -1); + cy = ts_get_attr_int(node, "y", -1); + if(cx < 0 || cy < 0 || cx >= sz || cy >= sz) { + fprintf(stderr, "ignoring cell with invalid or missing coordinates\n"); + continue; + } + cell = lvl->cells + cy * sz + cx; + cell->type = ts_get_attr_int(node, "blocked", 0) ? CELL_BLOCKED : CELL_WALK; + /* TODO wall tiles and detail objects */ + } + } + + ts_free_tree(ts); + return 0; +} + +int save_level(struct level *lvl, const char *fname) +{ + int i, j; + struct ts_node *root, *node; + struct ts_attr *attr; + struct cell *cell; + + if(!(root = ts_alloc_node()) || ts_set_node_name(root, "dunged_level") == -1) { + goto err; + } + + if(!(attr = ts_alloc_attr()) || ts_set_attr_name(attr, "size") == -1) { + ts_free_attr(attr); + goto err; + } + ts_set_valuei(&attr->val, lvl->width); + ts_add_attr(root, attr); + + for(i=0; iheight; i++) { + for(j=0; jwidth; j++) { + cell = lvl->cells + i * lvl->width + j; + if(cell->type == CELL_SOLID) continue; + + if(!(node = ts_alloc_node()) || ts_set_node_name(node, "cell") == -1) { + ts_free_node(node); + goto err; + } + if(!(attr = ts_alloc_attr()) || ts_set_attr_name(attr, "x") == -1) { + ts_free_attr(attr); + goto err; + } + ts_set_valuei(&attr->val, j); + ts_add_attr(node, attr); + if(!(attr = ts_alloc_attr()) || ts_set_attr_name(attr, "y") == -1) { + ts_free_attr(attr); + goto err; + } + ts_set_valuei(&attr->val, i); + ts_add_attr(node, attr); + + if(cell->type == CELL_BLOCKED) { + if(!(attr = ts_alloc_attr()) || ts_set_attr_name(attr, "blocked") == -1) { + ts_free_attr(attr); + goto err; + } + ts_set_valuei(&attr->val, 1); + ts_add_attr(node, attr); + } + + ts_add_child(root, node); + } + } + + if(ts_save(root, fname) == -1) { + fprintf(stderr, "failed to save level: %s\n", fname); + ts_free_tree(root); + return -1; + } + ts_free_tree(root); + return 0; + +err: + fprintf(stderr, "failed to construct treestore tree\n"); + ts_free_tree(root); + return -1; }