330 lines
9.4 KiB
C
330 lines
9.4 KiB
C
#include "ktkStructure.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <time.h> // for randomizeSeed
|
|
|
|
unsigned long ktk_RANDOM_SEED = 1;
|
|
|
|
unsigned long ktk_randomizeSeed() {
|
|
ktk_RANDOM_SEED = (unsigned long)time(0);
|
|
#if _WIN32 | _WIN64
|
|
srand(ktk_RANDOM_SEED);
|
|
#else
|
|
srandom(ktk_RANDOM_SEED);
|
|
#endif
|
|
return ktk_RANDOM_SEED;
|
|
}
|
|
|
|
int ktk_getRandom(int min, int max) {
|
|
int num;
|
|
if (min == 0 && max == 0) return 0;
|
|
if (min == max) return min;
|
|
// include max as a possible number (+1)
|
|
int range = (max+1) - min;
|
|
if (range >= RAND_MAX) {
|
|
printf("ktk_getRandom(%d, %d): ERROR, range beyond RAND_MAX!\n", min, max);
|
|
return 0;
|
|
} else if (range == 0) {
|
|
return min;
|
|
}
|
|
int buckets = RAND_MAX / range;
|
|
int limit = buckets * range;
|
|
#if _WIN32 | _WIN64
|
|
for (num = rand(); num >= limit; num = rand());
|
|
#else
|
|
for (num = random(); num >= limit; num = random());
|
|
#endif
|
|
return min + (num / buckets);
|
|
}
|
|
|
|
int ktk_rollNumber(struct ktkNumber number) {
|
|
return (ktk_getRandom(number.a, number.b));
|
|
if (number.type == ktk_PERCENT) {
|
|
|
|
} else if (number.type == ktk_DIGIT) {
|
|
|
|
}
|
|
}
|
|
int ktk_rollNumberSet(struct ktkNumberSet set) {
|
|
if (set.count <= 0) return 0;
|
|
return ktk_rollNumber(set.sets[ktk_getRandom(0, set.count-1)]);
|
|
}
|
|
int ktk_deleteNumberSet(struct ktkNumberSet *set) {
|
|
if (set->sets != NULL) {
|
|
free(set->sets);
|
|
set->sets = NULL;
|
|
set->count = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
int ktk_copyNumberSet(struct ktkNumberSet *set_1, struct ktkNumberSet *set_2) {
|
|
ktk_deleteNumberSet(set_2);
|
|
if (set_1->count > 0) {
|
|
set_2->sets = realloc(set_2->sets, set_1->count*sizeof(struct ktkNumber));
|
|
memcpy(set_2->sets, set_1->sets, set_1->count*sizeof(struct ktkNumber));
|
|
set_2->count = set_1->count;
|
|
} else {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
/*ktkField_t ktkStructureTable[] = {
|
|
{FIELD(flags)},
|
|
{FIELD(x)}, {FIELD(y)},
|
|
{FIELD(size_x)}, {FIELD(size_y)},
|
|
{FIELD(id_1)}, {FIELD(id_2)},
|
|
{FIELD(data)},
|
|
{FIELD(relations)}, {FIELD(relation_count)}
|
|
};
|
|
*/
|
|
//int ktk_setField(ktkField_t *table, size_t table_size,
|
|
|
|
const struct ktkStructure ktk_STRUCTURE_DEFAULT = {
|
|
0,
|
|
NULL,
|
|
{ 0, 0, 0}, { 0, 0, 0}, // x, y
|
|
{ 0, 0, 0}, { 0, 0, 0}, // size_x, size_y
|
|
{ NULL, 0}, // id_1
|
|
{ NULL, 0}, // id_2
|
|
{ NULL, 0}, // id_1 replace rules
|
|
{ NULL, 0}, // id_2 replace rules
|
|
NULL,
|
|
NULL, 0, // relations
|
|
NULL, 0 // paths + path count
|
|
};
|
|
void ktk_dumpStructure(struct ktkStructure *structure) {
|
|
printf("flags: %d\n", structure->flags);
|
|
printf("name: %s\n", structure->name);
|
|
printf("x: %dx%d\n", structure->x.a, structure->x.b);
|
|
printf("y: %dx%d\n", structure->y.a, structure->y.b);
|
|
printf("size_x: %dx%d\n", structure->size_x.a, structure->size_x.b);
|
|
printf("size_y: %dx%d\n", structure->size_y.a, structure->size_y.b);
|
|
}
|
|
|
|
int ktk_deleteStructure(struct ktkStructure *structure) {
|
|
if (structure->name != NULL) {
|
|
free(structure->name);
|
|
structure->name = NULL;
|
|
}
|
|
ktk_deleteNumberSet(&structure->id_1);
|
|
ktk_deleteNumberSet(&structure->id_2);
|
|
ktk_deleteNumberSet(&structure->replace_id_1);
|
|
ktk_deleteNumberSet(&structure->replace_id_2);
|
|
if (structure->relation_count > 0) {
|
|
int i;
|
|
for (i = 0; i < structure->relation_count; i++) {
|
|
//ktk_deleteLive(structure->relations[i]);
|
|
//free(structure->relations[i]);
|
|
free(structure->relations[i].name);
|
|
}
|
|
free(structure->relations);
|
|
structure->relations = NULL;
|
|
structure->relation_count = 0;
|
|
}
|
|
if (structure->path_count > 0) {
|
|
int i;
|
|
for (i = 0; i < structure->path_count; i++) {
|
|
free(structure->paths[i].name);
|
|
free(structure->paths[i].to);
|
|
free(structure->paths[i].from);
|
|
ktk_deleteNumberSet(&(structure->paths[i].to_x));
|
|
ktk_deleteNumberSet(&(structure->paths[i].to_y));
|
|
ktk_deleteNumberSet(&(structure->paths[i].from_x));
|
|
ktk_deleteNumberSet(&(structure->paths[i].from_y));
|
|
ktk_deleteNumberSet(&(structure->paths[i].x));
|
|
ktk_deleteNumberSet(&(structure->paths[i].y));
|
|
}
|
|
free(structure->paths);
|
|
structure->paths = NULL;
|
|
structure->path_count = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
const struct ktkRelation ktk_RELATION_DEFAULT = {
|
|
0,
|
|
NULL,
|
|
{ 0, 0, 0}, { 0, 0, 0},
|
|
{ 0, 0, 0}, { 0, 0, 0},
|
|
{ 1, 1, ktk_DIGIT},
|
|
};
|
|
|
|
const struct ktkLive ktk_LIVE_DEFAULT = {
|
|
NULL, // name of this
|
|
NULL, // parent
|
|
NULL, 0, // children and count
|
|
NULL, 0, // record pathing links + count of links
|
|
0,
|
|
0, 0, // x, y
|
|
0, 0, // size
|
|
0, 0, // id_1, id_2
|
|
NULL, // data
|
|
NULL // map?
|
|
};
|
|
|
|
struct ktkLive *ktk_getLiveRoot(struct ktkLive *live) {
|
|
struct ktkLive *current_live = live;
|
|
while (current_live->parent != NULL) {
|
|
current_live = current_live->parent;
|
|
}
|
|
return current_live;
|
|
}
|
|
|
|
struct ktkLive *ktk_getLive(struct ktkLive *live, const char *get, int match_offset) {
|
|
if (get == NULL) return NULL;
|
|
printf("offset: %d\n", match_offset);
|
|
struct ktkLive *current_live = live;
|
|
size_t get_len = strlen(get);
|
|
size_t get_offset = 0;
|
|
|
|
while (get_offset < get_len+1) {
|
|
if (get[get_offset] == ':') {
|
|
current_live = ktk_getLiveRoot(current_live);
|
|
get_offset++;
|
|
} else if (get[get_offset] == '^') {
|
|
if (current_live->parent != NULL) {
|
|
current_live = current_live->parent;
|
|
} else {
|
|
printf("could not get requested parent of %s\n", current_live->name);
|
|
return NULL;
|
|
}
|
|
get_offset++;
|
|
} else if (get[get_offset] == '\0') {
|
|
if (current_live == live) return NULL;
|
|
return current_live;
|
|
} else {
|
|
size_t sub_offset = get_offset;
|
|
while((get[sub_offset] != '^' && get[sub_offset] != ':')) {
|
|
if (get[sub_offset] == '\0') break;
|
|
sub_offset++;
|
|
}
|
|
char sub_name[sub_offset - get_offset+1];
|
|
memcpy(&sub_name, get+get_offset, sub_offset - get_offset);
|
|
sub_name[sub_offset-get_offset] = '\0';
|
|
size_t i;
|
|
int found = 0;
|
|
int match_current = 0;
|
|
for (i = 0; i < current_live->child_count; i++) {
|
|
if (strcmp(sub_name, current_live->children[i]->name) == 0) {
|
|
if (current_live->children[i] == current_live) continue; // we don't match ourself
|
|
if (get[sub_offset] == '\0') {
|
|
match_current++;
|
|
if (match_current > match_offset) {
|
|
current_live = current_live->children[i];
|
|
get_offset = sub_offset+1;
|
|
found = 1;
|
|
break;
|
|
}
|
|
} else {
|
|
current_live = current_live->children[i];
|
|
get_offset = sub_offset+1;
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!found) {
|
|
printf("could not find %s!\n", sub_name);
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
if (current_live == live) return NULL;
|
|
return current_live;
|
|
}
|
|
|
|
int ktk_addLink(struct ktkLive *live_1, struct ktkLive *live_2) {
|
|
live_1->link_count++;
|
|
live_1->links = realloc(live_1->links, live_1->link_count*sizeof(struct ktkLive*));
|
|
live_1->links[live_1->link_count-1] = live_2;
|
|
return 0;
|
|
}
|
|
int ktk_containsLink(struct ktkLive *live_1, struct ktkLive *live_2) {
|
|
int i;
|
|
for (i = 0; i < live_1->link_count; i++) {
|
|
if (live_1->links[i] == live_2) {
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int ktk_deleteLive(struct ktkLive *live) {
|
|
if (live->name != NULL) {
|
|
free(live->name);
|
|
live->name = NULL;
|
|
}
|
|
if (live->child_count > 0) {
|
|
int i;
|
|
for (i = 0; i < live->child_count; i++) {
|
|
ktk_deleteLive(live->children[i]);
|
|
free(live->children[i]);
|
|
}
|
|
free(live->children);
|
|
live->children = NULL;
|
|
live->child_count = 0;
|
|
}
|
|
if (live->link_count > 0) {
|
|
free(live->links);
|
|
live->links = NULL;
|
|
}
|
|
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;
|
|
child->parent = parent;
|
|
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
|
|
{NULL, 0}, // to x offset
|
|
{NULL, 0}, // to y offset
|
|
NULL, 0, // from structure in pathing syntax, from flags
|
|
{NULL, 0}, // from x offset
|
|
{NULL, 0}, // from y offset
|
|
{NULL, 0}, // x offset
|
|
{NULL, 0} // y offset
|
|
};
|
|
|
|
int ktk_explodeString(const char *string, char delim, int depth, char ***results) {
|
|
int words = 0, word_size = 1, word_i = 0;
|
|
int i = 0;
|
|
int len = strlen(string)+1;
|
|
// TODO: resize in 8-byte chunks or so
|
|
*results = malloc(1*sizeof(char*));
|
|
(*results)[words] = malloc(1*sizeof(char));
|
|
for (i = 0; i < len; i++) {
|
|
if ((string[i] == delim && words < depth) || string[i] == '\0') {
|
|
(*results)[words][word_i] = '\0';
|
|
*results = realloc(*results, (++words+1)*sizeof(char*));
|
|
(*results)[words] = malloc(1*sizeof(char));
|
|
//(*results)[words][0] = '\0';
|
|
word_i = 0;
|
|
word_size = 1;
|
|
} else {
|
|
(*results)[words] = realloc((*results)[words], ++word_size*sizeof(char));
|
|
(*results)[words][word_i++] = string[i];
|
|
}
|
|
}
|
|
return words;
|
|
}
|