Set up much of the base structure for Live Structures and Pathing. At the moment, most of the needed struct(s) and such are created and already inplace - however, some of the live generation needs to be fixed (pointers going to the wrong locations due to object duplication). Once that is in place, pathing should come fairly quickly...

master
kts 2014-11-17 05:02:00 -08:00
parent 00b4a72fd8
commit 90a0b3b484
9 changed files with 237 additions and 177 deletions

View File

@ -1,5 +1,6 @@
#include "ktkProgram.h"
#include <stdlib.h>
#include <string.h>
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;
for (i = 0; i < live_parent->child_count; i++) {
struct ktkLive *child = &(live_parent->children[i]);
ktk_linkStructures(program, child, orig_map);
}
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);
}
}
ktk_deleteMap(&map);
ktk_current_depth--;
return orig_map;
}*/
return 0;
}

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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)

8
main.c
View File

@ -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("#");*/

View File

@ -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
}
}
}