diff --git a/ktkProgram.c b/ktkProgram.c index 8c69435..6c8a99b 100644 --- a/ktkProgram.c +++ b/ktkProgram.c @@ -1,5 +1,6 @@ #include "ktkProgram.h" #include +#include int ktk_current_depth = 0; @@ -43,7 +44,7 @@ struct ktkStructure *ktk_getStructure(struct ktkProgram *program, const char *st return NULL; } -struct ktkMap *ktk_buildStructure(struct ktkProgram *program, struct ktkStructure *structure, struct ktkMap *orig_map) { +struct ktkMap *ktk_buildStructure(struct ktkProgram *program, struct ktkLive *live_parent, struct ktkStructure *structure, struct ktkMap *orig_map) { // limit our depth to avoid endless processing / seg fault ktk_current_depth++; if (ktk_current_depth >= ktk_LIMIT_DEPTH) { @@ -51,6 +52,11 @@ struct ktkMap *ktk_buildStructure(struct ktkProgram *program, struct ktkStructur return orig_map; } + // our live structure - this is copied to live_parent if structure is successful + struct ktkLive live = ktk_LIVE_DEFAULT; + live.parent = live_parent; + ktk_setLiveName(&live, structure->name); + int retry_limit = 64; int retry_count = 0; // retry is used if the structure is not allowed to overlap/replace/etc. @@ -79,6 +85,11 @@ struct ktkMap *ktk_buildStructure(struct ktkProgram *program, struct ktkStructur if (structure->size_y.type & ktk_PERCENT) { h = h * orig_map->h / 100; } + // create our live structure's position, etc. + live.x = x; + live.y = y; + live.size_x = w; + live.size_y = h; // *** step 1: create basic shape // generate the shape map struct ktkMap shape_map = ktk_MAP_DEFAULT; @@ -134,10 +145,7 @@ struct ktkMap *ktk_buildStructure(struct ktkProgram *program, struct ktkStructur if (relation->y.type & ktk_ISSET) { rel_structure.y = relation->y; } - //rel_structure.size_x = relation->size_x; - //rel_structure.size_y = relation->size_y; - ktk_buildStructure(program, &rel_structure, &structure_map); - //ktk_buildStructure(program, &rel_structure, &structure_map); + ktk_buildStructure(program, &live, &rel_structure, &structure_map); } } // *** step 5: retry if we've overlapped when we're not supposed to @@ -168,157 +176,34 @@ struct ktkMap *ktk_buildStructure(struct ktkProgram *program, struct ktkStructur } } } + ktk_addLiveChild(live_parent, &live); } else if (structure->flags & ktk_STRUCTURE_OVERLAP) { ktk_mergeMaps(orig_map, &structure_map); ktk_deleteMap(&structure_map); + ktk_addLiveChild(live_parent, &live); break; } else if (ktk_checkMapOverlap(orig_map, &structure_map) == 0) { ktk_mergeMaps(orig_map, &structure_map); ktk_deleteMap(&structure_map); + ktk_addLiveChild(live_parent, &live); break; } // if we reached here, that means we could not find a spot to draw + ktk_deleteLive(&live); ktk_deleteMap(&structure_map); } ktk_current_depth--; return orig_map; } -/* -struct ktkMap *ktk_buildStructure(struct ktkProgram *program, struct ktkStructure *structure, struct ktkMap *orig_map) { - if (ktk_current_depth >= ktk_LIMIT_DEPTH) return orig_map; - ktk_current_depth++; - struct ktkMap map = ktk_MAP_DEFAULT; - map.flags |= ktk_MAP_RESIZE; - if (structure == NULL) { - return orig_map; +int ktk_linkStructures(struct ktkProgram *program, struct ktkLive *live_parent, struct ktkMap *orig_map) { + if (live_parent->parent != NULL) { + printf("%s: parent is: %s\n", live_parent->name, live_parent->parent->name); } - // If a structure does not have a placement flag, it will be attempted to be placed multiple times. - int retry_limit = 8; - int retry = 0; - while(retry < retry_limit) { - int x, y, size_x, size_y; - // positioning logic - x = ktk_rollNumber(structure->x); - if (structure->x.type & ktk_PERCENT) { - x = x * orig_map->w / 100; - } - y = ktk_rollNumber(structure->y); - if (structure->y.type & ktk_PERCENT) { - y = y * orig_map->h / 100; - } - map.x = x; - map.y = y; - size_x = ktk_rollNumber(structure->size_x); - printf("prex: %d * %d / 100\n", size_x, orig_map->w); - if (structure->size_x.type & ktk_PERCENT) { - size_x = size_x * orig_map->w / 100; - } - size_y = ktk_rollNumber(structure->size_y); - printf("prey: %d * %d / 100\n", size_y, orig_map->h); - if (structure->size_y.type & ktk_PERCENT) { - size_y = size_y * orig_map->h / 100; - } - printf("creating: %dx%d\n", size_x, size_y); - // begin generation - ktk_resizeMap(&map, size_x, size_y); - // position logic - if (structure->flags & ktk_STRUCTURE_ORIGIN) { - map.x += size_x/2; - map.y += size_y/2; - } - // shape logic - // we use a separate shape map to get the workable area before drawing - //struct ktkMap shape_map = ktk_MAP_DEFAULT; - //ktk_resizeMap(&shape_map, size_x+1, size_y+1); - if (structure->flags & ktk_STRUCTURE_CIRCLE) { - ktk_fillEllipse(&map, 0, 0, size_x-1, size_y-1); - } else if (structure->flags & ktk_STRUCTURE_RECT) { - ktk_fillRect(&map, 0, 0, size_x, size_y); - } - if (structure->flags & ktk_STRUCTURE_BORDER) { - struct ktkMap border_map = ktk_MAP_DEFAULT; - border_map.flags |= ktk_MAP_RESIZE; - ktk_borderCells(&map, &border_map); - ktk_deleteMap(&map); - ktk_resizeMap(&map, size_x, size_y); - //map->flags &= ~ktk_MAP_RESIZE; - ktk_mergeMaps(&map, &border_map); - //map->flags |= ktk_MAP_RESIZE; - ktk_deleteMap(&border_map); - } - // fill logic - // if (structure->flags & ktk_STRUCTURE_FILL) { - int px, py; - for (px = 0; px < size_x; px++) { - for (py = 0; py < size_y; py++) { - if (map.cell[px][py].flags & ktk_CELL_EMPTY) continue; - map.cell[px][py].id_1 = ktk_rollNumberSet(structure->id_1); - map.cell[px][py].id_2 = ktk_rollNumberSet(structure->id_2); - map.cell[px][py].flags &= ~ktk_CELL_EMPTY; - } - } - // relations - int i; - int r_x, r_y; // relation x, y - int r_size_x, r_size_y; // relation size - - struct ktkMap snapshot = ktk_MAP_DEFAULT; - ktk_resizeMap(&snapshot, map.w, map.h); - printf("snapshot wxh: %dx%d\n", snapshot.w, snapshot.h); - ktk_mergeMaps(&snapshot, &map); - snapshot.flags |= ktk_MAP_RESIZE; - - for (i = 0; i < structure->relation_count; i++) { - struct ktkRelation *relation = &structure->relations[i]; - printf("running relation: %d:%s\n", i, relation->name); - // we tack on relation's flags to a new structure based on the target - struct ktkStructure *get_structure = ktk_getStructure(program, relation->name); - if (get_structure == NULL) continue; // TODO: add error - struct ktkStructure rel_structure = *get_structure; - rel_structure.flags |= relation->flags; - rel_structure.x = relation->x; - rel_structure.y = relation->y; - - printf("--dump--\n"); - ktk_dumpStructure(&rel_structure); - - int roll_count = ktk_rollNumber(relation->count); - int r; - for (r = 0; r < roll_count; r++) { - int retry_limit = 8; - struct ktkMap temp = ktk_MAP_DEFAULT; - ktk_resizeMap(&temp, snapshot.w, snapshot.h); - ktk_mergeMaps(&temp, &snapshot); - //temp.flags |= ktk_MAP_RESIZE; - printf("temp wxh: %dx%d\n", temp.w, temp.h); - //temp.x = snapshot.x; - //temp.y = snapshot.y; - ktk_buildStructure(program, &rel_structure, &temp); - if (rel_structure.flags & ktk_STRUCTURE_CONSTRAIN) { - map.flags &= ~ktk_MAP_RESIZE; - } - if (rel_structure.flags & ktk_STRUCTURE_OVERLAP || ktk_checkMapOverlap(&map, &temp) == 0) { - ktk_mergeMaps(&map, &temp); - } - if (rel_structure.flags & ktk_STRUCTURE_CONSTRAIN) { - map.flags |= ktk_MAP_RESIZE; - } - ktk_deleteMap(&temp); - } - } - ktk_deleteMap(&snapshot); - if (structure->flags & ktk_STRUCTURE_OVERLAP || ktk_checkMapOverlap(orig_map, &map) == 0) { - ktk_mergeMaps(orig_map, &map); - printf("no overlap found or flag is set\n"); - break; - } else { - printf("overlap found\n"); - retry++; - ktk_deleteMap(&map); - } + int i; + for (i = 0; i < live_parent->child_count; i++) { + struct ktkLive *child = &(live_parent->children[i]); + ktk_linkStructures(program, child, orig_map); } - ktk_deleteMap(&map); - ktk_current_depth--; - return orig_map; -}*/ + return 0; +} diff --git a/ktkProgram.h b/ktkProgram.h index e258a8c..99ac8c4 100644 --- a/ktkProgram.h +++ b/ktkProgram.h @@ -25,7 +25,8 @@ ktk_buildStructure This function finds the structure name in the given program and builds it into map. If the passed map is NULL, a new ktkMap is generated and returned. ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` */ -struct ktkMap *ktk_buildStructure(struct ktkProgram *program, struct ktkStructure *structure, struct ktkMap *map); +struct ktkMap *ktk_buildStructure(struct ktkProgram *program, struct ktkLive *live, struct ktkStructure *structure, struct ktkMap *orig_map); +int ktk_linkStructures(struct ktkProgram *program, struct ktkLive *live_parent, struct ktkMap *orig_map); struct ktkStructure *ktk_getStructure(struct ktkProgram *program, const char *structure_name); #endif diff --git a/ktkStructure.c b/ktkStructure.c index 7d74bf7..17f7248 100644 --- a/ktkStructure.c +++ b/ktkStructure.c @@ -84,7 +84,7 @@ const struct ktkStructure ktk_STRUCTURE_DEFAULT = { { NULL, 0}, // id_2 replace rules NULL, NULL, 0, // relations - NULL, 0 // sub structures + NULL, 0 // paths + path count }; void ktk_dumpStructure(struct ktkStructure *structure) { printf("flags: %d\n", structure->flags); @@ -101,15 +101,72 @@ const struct ktkRelation ktk_RELATION_DEFAULT = { { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 1, 1, ktk_DIGIT}, - NULL, - NULL, - 0, - NULL, - NULL, - 0, - NULL, - NULL, +}; + +const struct ktkLive ktk_LIVE_DEFAULT = { + NULL, // name of this + NULL, // parent + NULL, 0, // children and count 0, + 0, 0, // x, y + 0, 0, // size + 0, 0, // id_1, id_2 + NULL, // data + NULL // map? +}; + +int ktk_deleteLive(struct ktkLive *live) { + if (live->name != NULL) { + free(live->name); + live->name = NULL; + } + if (live->children != NULL) { + int i; + for (i = 0; i < live->child_count; i++) { + ktk_deleteLive(&(live->children[i])); + } + free(live->children); + live->children = NULL; + live->child_count = 0; + } + return 0; +} + +int ktk_addLiveChild(struct ktkLive *parent, struct ktkLive *child) { + parent->child_count++; + parent->children = realloc(parent->children, parent->child_count*sizeof(struct ktkLive)); + parent->children[parent->child_count-1] = *child; + // FIXME + int i; + for (i = 0; i < child->child_count; i++) { + child->children[i].parent = &(parent->children[parent->child_count-1]); + } + return 0; +} + +int ktk_setLiveName(struct ktkLive *live, const char *name) { + if (live->name != NULL) { + free(live->name); + live->name = NULL; + } + int size = strlen(name)+1; + live->name = malloc(size); + memcpy(live->name, name, size); + return 0; +} + +const struct ktkPath ktk_PATH_DEFAULT = { + NULL, // pathing structure name + NULL, // pathing structure + 0, // pathing flags + NULL, 0, // target structure in pathing syntax, target flags + {0, 0, 0}, // to x offset + {0, 0, 0}, // to y offset + NULL, 0, // from structure in pathing syntax, from flags + {0, 0, 0}, // from x offset + {0, 0, 0}, // from y offset + {0, 0, 0}, // x offset + {0, 0, 0} // y offset }; int ktk_explodeString(const char *string, char delim, int depth, char ***results) { diff --git a/ktkStructure.h b/ktkStructure.h index 5f6d621..394d914 100644 --- a/ktkStructure.h +++ b/ktkStructure.h @@ -60,10 +60,45 @@ struct ktkStructure { void *data; // user data (?) struct ktkRelation *relations; // behavioral relations to other Structures size_t relation_count; // count of said relations - struct ktkStructure *live; // live sub structures - size_t live_count; // count of sub structures + struct ktkPath *paths; // paths + size_t path_count; // count of paths }; extern const struct ktkStructure ktk_STRUCTURE_DEFAULT; void ktk_dumpStructure(struct ktkStructure *structure); +// live structures are similar to structures, but contain the resulting Structure +struct ktkLive { + char *name; // the name of this structure + // relationship map + struct ktkLive *parent; // parent of this structure + struct ktkLive *children; // children of this structure + size_t child_count; // count of chillens + // structure placement/size/etc. data + int flags; // creation flags + int x, y; // result position, in relative-to-parent terms + int size_x, size_y; // result size + int id_1; // result id_1 + int id_2; // result id_2 + void *data; // ? + struct ktkMap *map; // likely unused, but a snapshot of the generated map +}; extern const struct ktkLive ktk_LIVE_DEFAULT; + +int ktk_deleteLive(struct ktkLive *live); +// this function creates a shallow copy of child to parent - it retains pointers to the child's data. What this means is: DON'T deleteLive this child if you want to retain children. +int ktk_addLiveChild(struct ktkLive *parent, struct ktkLive *child); +int ktk_setLiveName(struct ktkLive *live, const char *name); + +struct ktkPath { + char *name; // name of the structure to use? + struct ktkStructure *structure; // base structure to use + int flags; // path generation flags + char *to; // target structure in pathing syntax + int to_flags; // target behavior flags + struct ktkNumber to_x, to_y; + char *from; // from structure in pathing syntax + int from_flags; // from behavior flags + struct ktkNumber from_x, from_y; + struct ktkNumber x; // x offset + struct ktkNumber y; // y offset +}; extern const struct ktkPath ktk_PATH_DEFAULT; // field table for ktkStructure /*#define S struct ktkStructure #define FIELD(m) #m,offsetof(S, m) @@ -90,15 +125,6 @@ struct ktkRelation { struct ktkNumber x, y; // x and y of the relation struct ktkNumber size_x, size_y; // size of created structure (generally) struct ktkNumber count; // count of times to run this relation - struct ktkStructure *from; // from this type of structure - char *from_name; // name of this structure - unsigned int from_flags; // from operating flags - struct ktkStructure *to; // to this type of structure - char *to_name; // name of this structure - unsigned int to_flags; // to operating flags - struct ktkStructure *path; // pathing Structure - char *path_name; // name of this structure - unsigned int path_flags; // pathing operating flags }; extern const struct ktkRelation ktk_RELATION_DEFAULT; #endif diff --git a/ktk_parse.c b/ktk_parse.c index cb87586..58bfc76 100644 --- a/ktk_parse.c +++ b/ktk_parse.c @@ -7,7 +7,7 @@ struct ktkNumber ktk_parseNumber(const char *text) { struct ktkNumber number = {0, 0, 0}; char **words = NULL; size_t w; - size_t word_count = ktk_explodeString(text, '-', 1024, &words); + size_t word_count = ktk_explodeString(text, '~', 1024, &words); // stupidly get our type with substring search if (strstr(text, "%") != NULL) { number.type |= ktk_PERCENT; @@ -63,6 +63,8 @@ int ktk_parseSFile(struct ktkProgram *program, const char *filename) { #define ktk_PARSE_RELATIONS 2 // find a relation state #define ktk_PARSE_RELATION_STRUCTURE 3// read relation structure vars #define ktk_PARSE_REPLACE 4 // read cell replace state + #define ktk_PARSE_PATHS 5 // find a path definition + #define ktk_PARSE_PATH_DEFINITION 6 // read path structure vars if ((file = fopen(filename, "r")) == NULL) { // TODO: set errcode return 1; @@ -123,6 +125,8 @@ int ktk_parseSFile(struct ktkProgram *program, const char *filename) { state = ktk_PARSE_RELATIONS; } else if (strcmp(words[0], "replace") == 0) { state = ktk_PARSE_REPLACE; + } else if (strcmp(words[0], "paths") == 0) { + state = ktk_PARSE_PATHS; } } else { ktk_parseSVars(&program->structures[program->structure_count-1], words, 2); @@ -171,6 +175,34 @@ int ktk_parseSFile(struct ktkProgram *program, const char *filename) { ktk_parseNumberSet(&(program->structures[program->structure_count-1].replace_id_2), words[1]); } } + // ** paths reading logic + } else if (state == ktk_PARSE_PATHS) { + word_count = ktk_explodeString(current_read, ' ', 1, &words); + if (word_count >= 1) { + if (words[1][0] == '{') { + // I'm bad. :) + program->structures[program->structure_count-1].path_count++; + program->structures[program->structure_count-1].paths = realloc(program->structures[program->structure_count-1].paths, program->structures[program->structure_count-1].path_count*sizeof(struct ktkPath)); + program->structures[program->structure_count-1].paths[program->structures[program->structure_count-1].path_count-1] = ktk_PATH_DEFAULT; + size_t name_size = strlen(words[0])+1; + program->structures[program->structure_count-1].paths[program->structures[program->structure_count-1].path_count-1].name = malloc(name_size*sizeof(char)); + memcpy(program->structures[program->structure_count-1].paths[program->structures[program->structure_count-1].path_count-1].name, words[0], name_size); + state = ktk_PARSE_PATH_DEFINITION; + } else if (words[0][0] == '}') { + state = ktk_PARSE_STRUCTURE; + } + } + } else if (state == ktk_PARSE_PATH_DEFINITION) { + word_count = ktk_explodeString(current_read, ' ', 1, &words); + if (word_count == 1) { + if (words[0][0] == '}') { + state = ktk_PARSE_PATHS; + } else { + ktk_parseSPath(&(program->structures[program->structure_count-1].paths[program->structures[program->structure_count-1].path_count-1]), words, word_count); + } + } else if (word_count == 2) { + ktk_parseSPath(&(program->structures[program->structure_count-1].paths[program->structures[program->structure_count-1].path_count-1]), words, word_count); + } } // **** end logic section **** // free our explode results @@ -192,7 +224,6 @@ int ktk_parseSFile(struct ktkProgram *program, const char *filename) { } } fclose(file); - return 0; } @@ -284,7 +315,44 @@ int ktk_parseSRelation(struct ktkRelation *relation, const char **vars, size_t v return 0; } -int ktk_parseSPath(struct ktkRelation *relation, const char **vars, size_t var_count) { +int ktk_parseSPath(struct ktkPath *path, const char **vars, size_t var_count) { + if (var_count == 2) { + if (strcmp(vars[0], "flags") == 0) { + char **words = NULL; + int w, word_count = 0; + word_count = ktk_explodeString(vars[1], '|', 1024, &words); + for (w = 0; w < word_count; w++) { + if (strcmp(words[w], "A*") == 0) { + } else if (strcmp(words[w], "DUMB") == 0) { + } else if (strcmp(words[w], "ALL") == 0) { + } + free(words[w]); + } + free(words); + } else if (strcmp(vars[0], "to") == 0) { + size_t size = strlen(vars[1])+1; + path->to = malloc(size); + memcpy(path->to, vars[1], size); + } else if (strcmp(vars[0], "to_flags") == 0) { + } else if (strcmp(vars[0], "to_x") == 0) { + path->to_x = ktk_parseNumber(vars[1]); + } else if (strcmp(vars[0], "to_y") == 0) { + path->to_y = ktk_parseNumber(vars[1]); + } else if (strcmp(vars[0], "from") == 0) { + size_t size = strlen(vars[1])+1; + path->from = malloc(size); + memcpy(path->from, vars[1], size); + } else if (strcmp(vars[0], "from_flags") == 0) { + } else if (strcmp(vars[0], "from_x") == 0) { + path->from_x = ktk_parseNumber(vars[1]); + } else if (strcmp(vars[0], "from_y") == 0) { + path->from_y = ktk_parseNumber(vars[1]); + } else if (strcmp(vars[0], "x") == 0) { + path->x = ktk_parseNumber(vars[1]); + } else if (strcmp(vars[0], "y") == 0) { + path->y = ktk_parseNumber(vars[1]); + } + } return 0; } diff --git a/ktk_parse.h b/ktk_parse.h index 338a447..4493510 100644 --- a/ktk_parse.h +++ b/ktk_parse.h @@ -28,4 +28,4 @@ This function is called by parseSFile and reads the given set of words into the ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` */ int ktk_parseSRelation(struct ktkRelation *relation, const char **vars, size_t var_count); -int ktk_parseSPath(struct ktkRelation *relation, const char **vars, size_t var_count); +int ktk_parseSPath(struct ktkPath *path, const char **vars, size_t var_count); diff --git a/logic.txt b/logic.txt index 7f0de91..e5a933b 100644 --- a/logic.txt +++ b/logic.txt @@ -32,6 +32,23 @@ Structure Generation Logic delete this.map 3. linking for structure in live.unlinked (limit calls somehow, so endless is avoided) + assuming structure generation as: + tree -> node + -> node -> subnode + tree -> other + if in first tree: + "node" refers to first node + "node:subnode" refers to any node with subnode + ":tree:other" -- first ":" denotes global, up to end ":" + if in subnode: + "^:^" - refers to tree, "$" means parent + "^:^:node" - refers to either parent or other node + + General link syntax: + "^" - parent of live structure + ":" - live sub structure of whatever context we're in + ":" - if first item, that means global - travel up to parent root and discover from there + get target structure { if target name[0] == ":" target = getLiveStructure(getLiveStructureRoot(live), name) diff --git a/main.c b/main.c index db76cdb..fd21e30 100644 --- a/main.c +++ b/main.c @@ -9,17 +9,21 @@ int main(int argc, char *argv[]) { struct ktkProgram my_program = ktk_PROGRAM_DEFAULT; ktk_parseSFile(&my_program, "test.txt"); + struct ktkLive my_live = ktk_LIVE_DEFAULT; + struct ktkMap my_map = ktk_MAP_DEFAULT; //ktk_resizeMap(&my_map, 10, 10); my_map.flags |= ktk_MAP_RESIZE; - ktk_buildStructure(&my_program, ktk_getStructure(&my_program, "rage"), &my_map); + ktk_buildStructure(&my_program, &my_live, ktk_getStructure(&my_program, "rage"), &my_map); + + //ktk_linkStructures(&my_program, &my_live, &my_map); //my_map.cell[2][2].id_1 = 1; int x, y; for (y = 0; y < my_map.h; y++) { for (x = 0; x < my_map.w; x++) { - if (my_map.cell[x][y].id_1 == 0) { + if (my_map.cell[x][y].flags & ktk_CELL_EMPTY) { printf("."); /* } else if (my_map.cell[x][y].id_1 == 1) { printf("#");*/ diff --git a/test.txt b/test.txt index fc1e21f..ee1442c 100644 --- a/test.txt +++ b/test.txt @@ -1,6 +1,6 @@ center { - size_x 14-17 - size_y 14-17 + size_x 14~17 + size_y 14~17 flags CIRCLE|FILL|BORDER|ORIGIN id_1 3 relations { @@ -27,8 +27,8 @@ walls { } room { - size_x 8-14 - size_y 8-14 + size_x 8~14 + size_y 8~14 relations { floor { flags ORIGIN @@ -80,11 +80,13 @@ rage { y 50% } room { - count 6-8 + count 6~8 flags ORIGIN - x 10-80% - y 10-80% + x 10~80% + y 10~80% } + } + paths { path { flags DUMB|ALL from center @@ -93,8 +95,8 @@ rage { to room to_x 25% to_y 25% - x 0-2 - y 0-2 + x 0~2 + y 0~2 } } }