diff options
| author | onelin <oscar@nelin.dk> | 2025-10-31 23:55:42 +0000 |
|---|---|---|
| committer | onelin <oscar@nelin.dk> | 2025-11-02 22:07:17 +0000 |
| commit | d38deeef3af2316a666f8fc0173940bd769b748e (patch) | |
| tree | 6e30d4a9eea18daa5705c894f28cd99ff047e8f9 /src/utils | |
| parent | 6c077751982ea2c7bd2d9262b01b9f8602f80dc8 (diff) | |
Flatten project structure
This will make it easier to break up the code into smaller chunks again
later.
One would think doing this seems fun to me at this point.
Diffstat (limited to 'src/utils')
| -rw-r--r-- | src/utils/CMakeLists.txt | 11 | ||||
| -rw-r--r-- | src/utils/include/engine/utils.h | 43 | ||||
| -rw-r--r-- | src/utils/include/engine/utils/btree.h | 61 | ||||
| -rw-r--r-- | src/utils/include/engine/utils/fov.h | 28 | ||||
| -rw-r--r-- | src/utils/include/engine/utils/hashmap.h | 61 | ||||
| -rw-r--r-- | src/utils/include/engine/utils/list.h | 18 | ||||
| -rw-r--r-- | src/utils/include/engine/utils/stack.h | 33 | ||||
| -rw-r--r-- | src/utils/src/btree.c | 800 | ||||
| -rw-r--r-- | src/utils/src/fov.c | 95 | ||||
| -rw-r--r-- | src/utils/src/hashmap.c | 5 | ||||
| -rw-r--r-- | src/utils/src/misc.c | 86 | ||||
| -rw-r--r-- | src/utils/src/stack.c | 82 |
12 files changed, 0 insertions, 1323 deletions
diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt deleted file mode 100644 index 6acdba1..0000000 --- a/src/utils/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -add_library(daw_utils - src/btree.c - src/fov.c - src/hashmap.c - src/misc.c - src/stack.c - ) - -target_compile_options(daw_utils PUBLIC ${BUILD_OPTS}) -target_include_directories(daw_utils PRIVATE ${DAW_INCLUDE_DIRS}) -target_link_libraries(daw_utils PRIVATE cglm) diff --git a/src/utils/include/engine/utils.h b/src/utils/include/engine/utils.h deleted file mode 100644 index 5096aa4..0000000 --- a/src/utils/include/engine/utils.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef ENGINE_UTILS_H -#define ENGINE_UTILS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <engine/core/types.h> -#include <cglm/ivec2.h> - -#define MIN(a, b) ((a < b) ? (a) : (b)) -#define MAX(a, b) ((a > b) ? (a) : (b)) - -#define MASK_TL (1 << 0) -#define MASK_T (1 << 1) -#define MASK_TR (1 << 2) -#define MASK_L (1 << 3) -#define MASK_C (1 << 4) -#define MASK_R (1 << 5) -#define MASK_BL (1 << 6) -#define MASK_B (1 << 7) -#define MASK_BR (1 << 8) - -/* Linear interpolate */ -f32 lerp(f32 dt, f32 a, f32 b); -i32 int_lerp(f32 dt, i32 a, i32 b); - -/* Hashes */ -u32 hash(char* str); - -/* Masks surrounding tiles of a kernel size of 3x3 */ -/* In reality we only need 9 bits for this, but I think I had a reason for using - * i32 */ -i32* kernmap(const void* map, i32* dstmap, const ivec2 mapsize, - predicate_t* predicate); - -/* Returns an index from the given weights. */ -i32 pick_from_sample(const i32* weights, i32 len); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/utils/include/engine/utils/btree.h b/src/utils/include/engine/utils/btree.h deleted file mode 100644 index 1dd2023..0000000 --- a/src/utils/include/engine/utils/btree.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef BTREE_H -#define BTREE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <stddef.h> - -#define BTREE_DEGREE_DEFAULT 4 - -#define BTREE_SIZE_MIN 8 -#define BTREE_SIZE_MAX 4096 - -#define BTREE_CMP_LT (-1) -#define BTREE_CMP_EQ (0) -#define BTREE_CMP_GT (1) - -struct btree; -struct btree_iter_t; - -/* elem_size: the size of the elements, typically `sizeof(struct <your struct>)` - * t: degree of the btree, if you're in doubt, use `BTREE_SIZE_DEFAULT` - * cmp: comparison function, in order to support any operations on the tree. - * - * This function just calls `btree_new_with_allocator` with `free` and `malloc` - * as initializers. - */ -struct btree* btree_new(size_t elem_size, size_t t, - int (*cmp)(const void* a, const void* b)); - -/* Same as `btree_new`, except that it actually initializes a btree, but with - * the given allocators. - */ -struct btree* btree_new_with_allocator(size_t elem_size, size_t t, - int (*cmp)(const void* a, const void* b), - void* (*alloc)(size_t), - void (*dealloc)(void*)); - -void btree_free(struct btree** btree); - -void* btree_search(struct btree* btree, void* elem); -void btree_insert(struct btree* btree, void* elem); -int btree_delete(struct btree* btree, void* elem); - -void btree_print(struct btree* btree, void (*print_elem)(const void*)); - -void* btree_first(struct btree* btree); -void* btree_last(struct btree* btree); - -size_t btree_size(struct btree* btree); - -struct btree_iter_t* btree_iter_t_new(struct btree* tree); -void btree_iter_t_reset(struct btree* tree, struct btree_iter_t** it); - -void* btree_iter(struct btree* tree, struct btree_iter_t* iter); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/utils/include/engine/utils/fov.h b/src/utils/include/engine/utils/fov.h deleted file mode 100644 index be64a9e..0000000 --- a/src/utils/include/engine/utils/fov.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef ENGINE_FOV_H -#define ENGINE_FOV_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <engine/core/types.h> -#include <stdbool.h> -#include <cglm/ivec2.h> - -/* `fov_shadowcast`: */ -/* map: your 2D enum tile grid - * mapsize: x: width, y: height of the map - * visblocking: pointer to a function that returns `true` when receiving a - * pointer to a LOS blocking tile - * lightmap: [out] 2D lightmap, this is simply overwritten with the - * distance to the source. range: visibility range/radius. src: 2D - * point to calculate FOV from - * */ -void fov_shadowcast(const void* map, const ivec2 mapsize, - bool (*visblocking)(const void*), i32* lightmap, - const i32 range, const ivec2 src); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/utils/include/engine/utils/hashmap.h b/src/utils/include/engine/utils/hashmap.h deleted file mode 100644 index 0113ce5..0000000 --- a/src/utils/include/engine/utils/hashmap.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef ENGINE_HASHMAP_H -#define ENGINE_HASHMAP_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <stdlib.h> - -#include <engine/core/types.h> -#include <engine/core/memory.h> -#include <engine/utils/list.h> - -usize lolhash(const usize s, usize v); - -/* Define a linked list before using this */ -/* Example: DEFINE_LLIST(i32) */ -#define DEFINE_HASHMAP(type, lsize, cmp, type_to_int) \ - typedef DEFINE_LLIST(type); \ - typedef struct hashmap_##type { \ - usize size; \ - List_##type elems[64]; \ - } hashmap_##type; \ - \ - type* hashmap_##type##_lookup(hashmap_##type* hmap, const type* val) { \ - const usize idx = lolhash(64, type_to_int(val)); \ - List_##type* head = &hmap->elems[idx]; \ - while (head != NULL) { \ - if (!cmp(&(head->value), val)) return &(head->value); \ - head = head->next; \ - } \ - return NULL; \ - } \ - \ - void hashmap_##type##_insert(memory* m, hashmap_##type* hmap, \ - const type* val) { \ - const usize idx = lolhash(64, type_to_int(val)); \ - List_##type* head = &(hmap->elems[idx]); \ - \ - /* This is highly dependant on whether the memory is zero-initialized */ \ - if (!type_to_int(&(head->value))) { \ - memcpy(&(head->value), val, sizeof(type)); \ - return; \ - } \ - \ - while (head->next != NULL && cmp(&head->value, val)) { \ - head = head->next; \ - } \ - \ - if (!cmp(&head->value, val)) \ - memcpy(&(head->value), val, sizeof(type)); \ - else { \ - head->next = memory_allocate(m, sizeof(List_##type)); \ - memcpy(&(head->next->value), val, sizeof(type)); \ - } \ - } - -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/utils/include/engine/utils/list.h b/src/utils/include/engine/utils/list.h deleted file mode 100644 index 04dda04..0000000 --- a/src/utils/include/engine/utils/list.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef ENGINE_LIST_H -#define ENGINE_LIST_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define DEFINE_LLIST(type) \ - struct List_##type { \ - type value; \ - struct List_##type* next; \ - /* Force the user to add `;` for style consistency */ \ - } List_##type - -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/utils/include/engine/utils/stack.h b/src/utils/include/engine/utils/stack.h deleted file mode 100644 index b4caf5f..0000000 --- a/src/utils/include/engine/utils/stack.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef STACK_H -#define STACK_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <engine/core/types.h> - -typedef struct { - usize head; /* current number of elements */ - const usize elem_size; /* size in bytes of each element */ - usize size; /* current memory size used by the stack */ - const usize chunk_size; /* size of which the stack increases when running out - of mem */ - void* data; /* memory buffer */ -} Stack; - -Stack stack_new_ex(const usize element_size, const usize size); - -Stack stack_new(const usize element_size); - -void stack_free(Stack* s); -void* stack_pop(Stack* s); -void stack_push(Stack* s, void* elem); -void* stack_peek(Stack* s); -usize stack_size(const Stack* s); -void stack_swap(Stack* s, Stack* t); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/utils/src/btree.c b/src/utils/src/btree.c deleted file mode 100644 index 9411072..0000000 --- a/src/utils/src/btree.c +++ /dev/null @@ -1,800 +0,0 @@ -#include <engine/utils/btree.h> - -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <sys/types.h> - -/* Definitions */ -typedef unsigned char byte; - -struct node { - size_t n; /* number of items/keys/elements */ - size_t c; /* number of children */ - byte* items; - struct node** children; -}; - -struct btree { - /* Memory stuffs */ - void* (*alloc)(size_t); - void (*dealloc)(void*); - - /* Size stuffs */ - size_t elem_size; - size_t degree; - - struct node* root; - - /* comparison */ - int (*cmp)(const void* a, const void* b); -}; - -struct btree_iter_t { - size_t head; - struct stack { - int pos; - struct node* node; - } stack[512]; - /* This heavily relies on the assumption that a tree never grows deeper than - * 512 nodes */ -}; - -/**********************/ -/* Node functionality */ -/**********************/ -#define node_leaf(node) (node->children == NULL) - -#define node_maxdegree(t) (2 * t - 1) - -#define node_mindegree(t) (t - 1) - -#define node_full(degree, t) (t->n >= 2 * degree - 1) - -/* Node memory */ - -/* `node_new` allocates a new leaf node, children should be added and allocated - * when the node is no longer a leaf node */ -struct node* node_new(const size_t degree, const size_t elem_size) { - const size_t max_items = 2 * degree; - struct node* retval = calloc(1, sizeof(struct node)); - - retval->n = 0; - retval->c = 0; - retval->items = calloc(max_items, elem_size); - retval->children = NULL; - - return retval; -} - -/* `node_transition` turns a leaf node into a non-leaf. Children are not - * allocated. - * returnvalue: `false` if we we're unable to allocate space for the new - * children. */ -bool node_transition(struct node* node, const size_t degree) { - const size_t max_children = 2 * degree + 1; - size_t c; - - if (!node_leaf(node)) { - perror("node_transition was called on an already non-leaf node?"); - return false; - } - - /* Allocate pointers for children */ - node->children = calloc(max_children, sizeof(struct node*)); - - if (node->children == NULL) { - perror("could not allocate space for children pointers"); - return false; - } - - /* Allocate children */ - for (c = 0; c < max_children; c++) { - node->children[c] = NULL; - } - - return true; -} - -void node_free(struct node** node, size_t elem_size, void (*dealloc)(void*)) { - if (*node == NULL) return; - - if (!node_leaf((*node))) { - size_t i; - for (i = 0; i < (*node)->c; i++) { - node_free(&((*node)->children[i]), elem_size, dealloc); - } - dealloc((*node)->children); - } - - dealloc((*node)->items); - (*node)->items = NULL; - - dealloc(*node); - *node = NULL; -} - -/* `node_tree_split_child` splits a _full_ node (c = 2t-1 items) into two nodes - * with t-1 items each. - * The median key/item/element moves up to the original nodes parent, to signify - * the split. If the parent is full too, we need to split it before inserting - * the median key. - * This can potentially split full nodes all the way up throughout the tree. */ -/* Instead of waiting to find out wether we should split the nodes, we split the - * full nodes we encounter on the way down, including the leafs themselves. - * By doing this, we are assured that whenever we split a node, its parent has - * room for the median key. */ -void node_tree_split_child(const size_t t, const size_t elem_size, - struct node* nonfull, size_t i) { - struct node* z = node_new(t, elem_size); - struct node* y = nonfull->children[i]; - size_t j; - - /* `z` should be a branching node if `y` is */ - if (!node_leaf(y)) { - node_transition(z, t); - } - - z->n = t - 1; - - /* Move last `t-1` items to new node `z` */ - /* TODO This can be done with one memcpy */ - for (j = 0; j < t - 1; j++) { - const size_t offset_dst = elem_size * j; - const size_t offset_src = elem_size * (t + j); - memcpy((z->items) + offset_dst, (y->items) + offset_src, elem_size); - } - /* Set unused item-memory to zero? */ - - /* Move children t..2t, if applicable*/ - if (!node_leaf(y)) { - for (j = 0; j < t + 1; j++) { - z->children[j] = y->children[j + t]; - } - y->c = t; - z->c = t; - } - - y->n = t - 1; - - /* Move children +1 */ - for (j = nonfull->n; j > i; j--) { - nonfull->children[j + 1] = nonfull->children[j]; - } - - /* new child */ - nonfull->children[i + 1] = z; - nonfull->c++; - - /* moving keys i..n + 1*/ - /* TODO This can be done with one memcpy */ - for (j = nonfull->n; j >= i; j--) { - const size_t offset = j * elem_size; - memcpy((nonfull->items) + offset + elem_size, (nonfull->items) + offset, - elem_size); - } - - /* Lastly, copy the median element to nonfull-parent*/ - memcpy((nonfull->items) + i * elem_size, (y->items) + (t - 1) * elem_size, - elem_size); - - nonfull->n++; -} - -/* `node_child_merge`: Merges two children around the key at index `i` (k) - * by appending k to the left child (y) followed by - * appending the right child (z) to y - * - * `x`: The parent node of y and z - * `i`: Index of the item that acts as the new median of the merged node - * - * WARNING: THIS FUNCTION ASSUMES THAT `i` IS A VALID INDEX - */ -void node_child_merge(struct node* x, size_t i, const size_t elem_size, - void (*dealloc)(void*)) { - struct node* y = x->children[i]; - struct node* z = x->children[i + 1]; - size_t j = 0; - - /* append k to y */ - memcpy(y->items + (elem_size * y->n++), x->items + (elem_size * i), - elem_size); - - /* append keys in z to y */ - memcpy(y->items + (elem_size * y->n), z->items, elem_size * z->n); - y->n += z->n; - - /* Move children from z to y */ - for (j = 0; j < z->c; j++) { - y->children[y->c + j] = z->children[j]; - } - y->c += z->c; - - /* Remove z from x */ - for (j = i + 1; j < x->c; j++) { - x->children[j] = x->children[j + 1]; - } - x->c--; - - /* remove k from x */ - /* TODO check if we need to use (x->n - 1 - i) instead */ - memmove(x->items + (elem_size * i), x->items + (elem_size * (i + 1)), - elem_size * (x->n - i)); - x->n--; - - dealloc(z); /* DO NOT USE THE RECURSIVE ONE AS CHILDREN WILL BE LOST!!! */ -} - -/* ASSUME i < x->c */ -void node_shift_left(struct node* x, size_t i, const size_t elem_size) { - struct node* y = x->children[i]; - struct node* z = x->children[i + 1]; - byte* x_k = x->items + (elem_size * i); - - /* Append x.k[i] to y */ - memcpy(y->items + (elem_size * y->n++), x_k, elem_size); - - /* Move first element of z to x.k[i] */ - memcpy(x_k, z->items, elem_size); - - /* Shift z's items left */ - memmove(z->items, z->items + elem_size, elem_size * (z->n - 1)); - - if (!node_leaf(z)) { - size_t j; - /* append first child of z to y */ - y->children[y->c++] = z->children[0]; - - /* Shift z's children left */ - for (j = 0; j < z->c; j++) { - z->children[j] = z->children[j + 1]; - } - z->c--; - } - - z->n--; -} - -void node_shift_right(struct node* x, size_t i, const size_t elem_size) { - struct node* y = x->children[i]; - struct node* z = x->children[i + 1]; - byte* x_k = x->items + (elem_size * i); - - /* Shift z's items right */ - memmove(z->items + elem_size, z->items, elem_size * z->n); - - /* Prepend x.k[i] to z */ - memcpy(z->items, x_k, elem_size); - - /* Move last element of y to x.k[i] */ - memcpy(x_k, y->items + (elem_size * --(y->n)), elem_size); - - if (!node_leaf(z)) { - size_t j; - /* Shift z's children right */ - for (j = z->c; j > 0; j--) { - z->children[j] = z->children[j - 1]; - } - z->c++; - - /* prepend last child of y to z */ - z->children[0] = y->children[--(y->c)]; - } - - z->n++; -} - -/* return: Returns the new root, if a split happens */ -void node_insert_nonfull(struct node* root, void* elem, const size_t degree, - const size_t elem_size, - int (*cmp)(const void* a, const void* b)) { - - /* TODO check correctness */ - size_t i = root->n - 1; - - if (node_leaf(root)) { - size_t offset = elem_size * i; - while (i >= 0 && cmp(elem, root->items + offset) < 0) { - /* TODO This can be done with one memcpy */ - memcpy(root->items + offset + elem_size, root->items + offset, elem_size); - - i--; - offset = elem_size * i; - } - offset = elem_size * (++i); - memcpy(root->items + offset, elem, elem_size); - root->n++; - - } else { - size_t offset = elem_size * i; - struct node* nextchild = NULL; - while (i >= 0 && cmp(elem, root->items + offset) < 0) { - i--; - offset = elem_size * i; - } - i++; - nextchild = root->children[i]; - if (node_full(degree, nextchild)) { - /* TODO Check if the root has changed */ - node_tree_split_child(degree, elem_size, root, i); - if (cmp(elem, root->items + elem_size * i) > 0) { - nextchild = root->children[++i]; - } - } - node_insert_nonfull(nextchild, elem, degree, elem_size, cmp); - } -} - -/* Returns the new root, if a split occurs */ -struct node* node_insert(struct node* root, void* elem, const size_t degree, - const size_t elem_size, - int (*cmp)(const void* a, const void* b)) { - - struct node* s = root; - - if (node_full(degree, root)) { - s = node_new(degree, elem_size); - if (s == NULL) { - fputs("BTree error: Failed to allocate new node for insertion!\n", - stderr); - return NULL; - } - node_transition(s, degree); - s->children[s->c++] = root; - /* TODO Check if the root has changed */ - node_tree_split_child(degree, elem_size, s, 0); - node_insert_nonfull(s, elem, degree, elem_size, cmp); - } else { - node_insert_nonfull(s, elem, degree, elem_size, cmp); - } - return s; -} - -void* node_search(struct node* x, void* key, - int (*cmp)(const void* a, const void* b), - const size_t elem_size) { - /* We set to one, since we pre-emptively do a comparison with the assumption - * that there's already one in the items */ - size_t i = 0; - int last_cmp_res = 0; - - while (i < x->n && - (last_cmp_res = cmp(key, (const void*)(x->items + (i * elem_size)))) > - 0) { - i++; - } - - if (i < x->n && last_cmp_res == 0) { - return (void*)(x->items + (i * elem_size)); - } else if (node_leaf(x)) { - return NULL; - } - - /* Assumption: ¬node_leaf(x) → x.children is allocated */ - return node_search(x->children[i], key, cmp, elem_size); -} - -int node_delete(struct node* x, void* key, - int (*cmp)(const void* a, const void* b), const size_t degree, - const size_t elem_size, void* (*alloc)(size_t), - void (*dealloc)(void*)) { - /* Determine wether the key is in the node */ - size_t i = 0; /* Index of `k`, if found */ - int last_cmp_res = 0; - - while (i < x->n && - (last_cmp_res = cmp(key, (const void*)(x->items + (i * elem_size)))) > - 0) { - i++; - } - - if (last_cmp_res == 0) { - - if (node_leaf(x)) { - /* 1. k ϵ x && node_leaf(x) */ - /* Delete k from x */ - size_t j = i; - while (j + 1 < x->n) { - const size_t offset_dst = elem_size * j; - const size_t offset_src = elem_size * (j + 1); - memcpy((x->items) + offset_dst, (x->items) + offset_src, elem_size); - j++; - } - x->n--; - return 1; - } else { - /* 2. k ϵ x && !node_leaf(x) */ - /* let i be the index of k in x */ - /* 2a: if size(child[i]) >= t; find the largest k' in child[i] */ - /* replace k with k' */ - if (x->children[i]->n >= degree) { - struct node* y = x->children[i]; - byte* kk = alloc(elem_size); - - /* Find the predecessor, k' of k in y */ - { - struct node* tmp = y; - while (!node_leaf(tmp)) { - tmp = tmp->children[tmp->n - 1]; - } - - /* copy kk */ - memcpy(kk, tmp->items + elem_size * (tmp->n - 1), elem_size); - } - - /* Recursively delete kk from y */ - return node_delete(y, kk, cmp, degree, elem_size, alloc, dealloc); - - /* replace k with kk */ - memcpy(x->items + (elem_size * i), kk, elem_size); - - dealloc(kk); - - return 1; - - } else if (x->children[i + 1]->n >= degree) { - struct node* z = x->children[i + 1]; - byte* kk = alloc(elem_size); - - /* Find the successor, k' of k in z */ - { - struct node* tmp = z->children[0]; - while (!node_leaf(tmp)) { - tmp = tmp->children[0]; - } - - /* copy kk */ - memcpy(kk, tmp->items + elem_size * (tmp->n - 1), elem_size); - } - - /* Recursively delete kk from y */ - return node_delete(z, kk, cmp, degree, elem_size, alloc, dealloc); - - /* replace k with kk */ - memcpy(x->items + (elem_size * i), kk, elem_size); - - dealloc(kk); - - return 1; - } else { - /* Merge k and z into y */ - node_child_merge(x, i, elem_size, dealloc); - - /* recurse */ - return node_delete(x->children[i], key, cmp, degree, elem_size, alloc, - dealloc); - } - } - } else if (node_leaf(x)) { - return 0; - } else { - /* 3. !(k ϵ x) */ - - /* if x is a leaf, then it is not in the tree */ - - struct node* y; - size_t ii; /* index of x.c[i] */ - - /* Determine x.c[i] that must contain k */ - /* if last cmp < 0, then the child must be in the left child of x.items[i]*/ - if (last_cmp_res < 0) ii = i; - /* Otherwise, it must be the very last child */ - else if (i < x->n) - ii = i + 1; - else - ii = i; - - y = x->children[ii]; - - if (y->n < degree) { - /* we are left biased */ - if (ii > 0 && x->children[ii - 1]->n >= degree) { - node_shift_right(x, ii - 1, elem_size); - - } else if (ii < x->c - 1 && x->children[ii + 1]->n >= degree) { - node_shift_left(x, ii, elem_size); - - } else { - /* We need to determine wether we merge left or right, if possible */ - if (ii > 0) { - node_child_merge(x, ii - 1, elem_size, dealloc); - y = x->children[ii - 1]; - } else if (ii < x->c - 1) { - node_child_merge(x, ii, elem_size, dealloc); - } else { - perror("Cannot merge!"); - } - } - } - - return node_delete(y, key, cmp, degree, elem_size, alloc, dealloc); - } - return 0; -} - -/***********************/ -/* Btree functionality */ -/***********************/ -struct btree* btree_new(size_t elem_size, size_t t, - int (*cmp)(const void* a, const void* b)) { - return btree_new_with_allocator(elem_size, t, cmp, malloc, free); -} - -struct btree* btree_new_with_allocator(size_t elem_size, size_t t, - int (*cmp)(const void* a, const void* b), - void* (*alloc)(size_t), - void (*dealloc)(void*)) { - struct btree* new_tree = alloc(sizeof(struct btree)); - - new_tree->alloc = alloc; - new_tree->dealloc = dealloc; - - new_tree->elem_size = elem_size; - new_tree->degree = t; - - new_tree->root = NULL; - - new_tree->cmp = cmp; - - return new_tree; -} - -void btree_free(struct btree** btree) { - node_free(&((*btree)->root), (*btree)->elem_size, (*btree)->dealloc); - (*btree)->dealloc(*btree); - *btree = NULL; -} - -void btree_insert(struct btree* btree, void* elem) { - if (btree == NULL) { - fputs("BTree error: Inserting into a NULL ptr!\n", stderr); - return; - } - if (elem == NULL) { - fputs("BTree error: Inserting NULL into a tree!\n", stderr); - return; - } - if (btree->root == NULL) { - btree->root = node_new(btree->degree, btree->elem_size); - if (btree->root == NULL) { - fputs("BTree error: Failed to create new root node!\n", stderr); - return; - } - node_insert(btree->root, elem, btree->degree, btree->elem_size, btree->cmp); - } else { - btree->root = node_insert(btree->root, elem, btree->degree, - btree->elem_size, btree->cmp); - } -} - -void* btree_search(struct btree* btree, void* elem) { - return node_search(btree->root, elem, btree->cmp, btree->elem_size); -} - -int btree_delete(struct btree* btree, void* elem) { - struct node* newroot = btree->root; - int res = node_delete(btree->root, elem, btree->cmp, btree->degree, - btree->elem_size, btree->alloc, btree->dealloc); - if (newroot->n == 0) { - if (node_leaf(newroot)) return res; - /* shrink the tree */ - struct node* newroot_p = newroot->children[0]; - btree->dealloc(newroot); - btree->root = newroot_p; - } - return res; -} - -void node_print(struct node* root, const size_t elem_size, const int indent, - void (*print_elem)(const void*)) { - size_t i; - int t; - - for (t = 0; t < indent - 1; t++) { - fputs(" ┃ ", stdout); - } - if (indent > 0) { - fputs(" ┣┯", stdout); - } - printf("printing node \x1b[33m%0lx\x1b[0m," - " c:%ld n:%ld\t\t" - "\x1b[30m%p\x1b[0m\n", - (unsigned long)((size_t)root % 0x10000), root->c, root->n, - (void*)root); - - if (node_leaf(root)) { - for (i = 0; i < root->n - 1; i++) { - const size_t ofst = i * elem_size; - for (t = 0; t < indent; t++) { - fputs(" ┃├", stdout); - } - print_elem(root->items + ofst); - } - for (t = 0; t < indent; t++) { - fputs(" ┃└", stdout); - } - print_elem(root->items + i * elem_size); - } else { - size_t ofst = 0; - for (i = 0; i < root->c - 1; i++) { - node_print(root->children[i], elem_size, indent + 1, print_elem); - for (t = 0; t < indent; t++) { - fputs(" ┃ ", stdout); - } - print_elem(root->items + ofst); - ofst += elem_size; - } - node_print(root->children[i], elem_size, indent + 1, print_elem); - } -} - -void btree_print(struct btree* btree, void (*print_elem)(const void*)) { - printf("BTRee: degree:%ld\n", btree->degree); - if (btree->root == NULL) return; - node_print(btree->root, btree->elem_size, 0, print_elem); -} - -void* btree_first(struct btree* btree) { - struct node* root; - if (btree == NULL) return NULL; - root = btree->root; - - if (root == NULL) return NULL; - - while (!node_leaf(root)) root = root->children[0]; - - if (root->n == 0) return NULL; - return root->items; /* Return first element */ -} - -void* btree_last(struct btree* btree) { - struct node* root; - - if (btree == NULL) return NULL; - root = btree->root; - - if (root == NULL) return NULL; - - while (!node_leaf(root)) root = root->children[root->c]; - - if (root->n == 0) return NULL; - return root->items + - btree->elem_size * (root->n - 1); /* Return first element */ -} - -size_t btree_height(struct btree* btree) { - struct node* root; - size_t height = 0; - - if (btree == NULL) return 0; - root = btree->root; - - if (root == NULL) return 0; - - while (!node_leaf(root)) { - root = root->children[0]; - height++; - } - - return height; -} - -size_t u32_pow(size_t base, size_t exponent) { - size_t res = 1; - while (exponent > 0) { - res *= base; - exponent--; - } - return res; -} - -size_t btree_size(struct btree* btree) { - return u32_pow(2 * btree->degree, btree_height(btree)) - 1; -} - -struct btree_iter_t* btree_iter_t_new(struct btree* tree) { - struct btree_iter_t* iter = NULL; - - if (tree == NULL) return NULL; - - iter = (struct btree_iter_t*)tree->alloc(sizeof(struct btree_iter_t)); - - if (tree != NULL) { - iter->head = 0; - memset(iter->stack, 0, 512 * sizeof(struct node*)); - - iter->stack[iter->head].pos = 0; - iter->stack[iter->head].node = tree->root; - } else { - perror("Cannot instantiate iterator from null-pointer tree"); - } - return iter; -} - -void btree_iter_t_reset(struct btree* tree, struct btree_iter_t** it) { - (*it)->head = 0; - - (*it)->stack[0].pos = 0; - (*it)->stack[0].node = tree->root; -} - -void* btree_iter(struct btree* tree, struct btree_iter_t* iter) { - register int pos = 0; - register size_t head = 0; - register size_t n = 0; - - if (iter->stack[head].node == NULL) return NULL; - - head = iter->head; - pos = iter->stack[head].pos; - n = iter->stack[head].node->n; - -#define BTREE_ITER_POP(it) \ - { \ - iter->stack[head].pos = 0; \ - iter->stack[head].node = NULL; \ - iter->head--; \ - head--; \ - iter->stack[head].pos++; \ - \ - pos = iter->stack[head].pos; \ - n = iter->stack[head].node->n; \ - } - - /* Check if we have reached the end of a node. - * Take note of the difference of inequality in the if statement and - * following while */ - - /* Leafs are a special case, as, if the only node is the root node, we might - * want to exit */ - if (node_leaf(iter->stack[iter->head].node) && (size_t)pos >= 2 * n) { - if (head == 0) return NULL; - - /* Pop, if so */ - else - BTREE_ITER_POP(iter); - } - - /* Otherwise, pop while we have reached the end of a node */ - while ((size_t)pos > 2 * n) { - if (head == 0) return NULL; - - /* Pop, if so */ - else - BTREE_ITER_POP(iter); - } - -#undef BTREE_ITER_POP - - /* On evens, we decent into children */ - if (!node_leaf(iter->stack[head].node)) { - if (pos % 2 == 0) { - /* push child node onto iter->stack */ - iter->stack[head + 1].pos = 0; - iter->stack[head + 1].node = iter->stack[head].node->children[pos / 2]; - iter->head++; - head++; - - /* Decent all the way to the left, if pos == 0 */ - while (!node_leaf(iter->stack[iter->head].node)) { - iter->stack[head + 1].pos = 0; - iter->stack[head + 1].node = iter->stack[head].node->children[0]; - iter->head++; - head++; - } - } - } - - /* Finally, update index and return a value */ - if (node_leaf(iter->stack[head].node)) { - iter->stack[head].pos += 2; - pos = iter->stack[head].pos; - } else { - iter->stack[head].pos++; - pos = iter->stack[head].pos; - } - - return iter->stack[head].node->items + tree->elem_size * (((size_t)pos - 1) / 2); -} diff --git a/src/utils/src/fov.c b/src/utils/src/fov.c deleted file mode 100644 index 90df5af..0000000 --- a/src/utils/src/fov.c +++ /dev/null @@ -1,95 +0,0 @@ -#include <engine/utils/fov.h> -#include <engine/utils.h> -#include <math.h> -#include <stdint.h> - -void fov_shadowcast_rec(const void* map, const ivec2 mapsize, - bool (*visblocking)(const void*), i32* lightmap, - const i32 range, ivec2 src, const i32 row, f32 start, - const f32 end, const i8 xx, const i8 xy, const i8 yx, - const i8 yy) { - - if (start < end) return; - - const i32 range_2 = range * range; - f32 new_start = start; - - for (i32 i = row; i <= range; i++) { - i32 dx = (-1 * i) - 1; - i32 dy = -1 * i; - - bool blocked = false; - - while (dx <= 0) { - dx += 1; - - const i32 mapx = src[0] + dx * xx + dy * xy; - const i32 mapy = src[1] + dx * yx + dy * yy; - - const f32 slope_l = (((f32)dx) - 0.5f) / (((f32)dy) + 0.5f); - const f32 slope_r = (((f32)dx) + 0.5f) / (((f32)dy) - 0.5f); - - if (start < slope_r) continue; - if (end > slope_l) break; - - if (dx * dx + dy * dy < range_2) { - /* set as visible */ - if (mapx >= 0 && mapx < (long)mapsize[0] && mapy >= 0 && - mapy < (long)mapsize[1]) { - // TODO: Calculate proper dist from source - i32 x_2 = (src[0] - mapx) * (src[0] - mapx); - i32 y_2 = (src[1] - mapy) * (src[1] - mapy); - lightmap[mapy * mapsize[0] + mapx] = - MAX(lightmap[mapy * mapsize[0] + mapx], - (i32)(range - sqrt((f64)(x_2 + y_2)))); - } - } - - /* sizeof(i32) is the size of enums */ - /* -- unless the compiler doesn't follow standard behaviour */ - const bool is_blocked = visblocking( - (void*)((u64)map - + sizeof(i32) /* ~ enum size */ - * (usize)(mapsize[0] * mapy + mapx) /* index */ - )); - - if (blocked) { - if (!is_blocked) { - new_start = slope_r; - } else { - blocked = false; - start = new_start; - } - } else if (!is_blocked && i < range) { - blocked = true; - fov_shadowcast_rec(map, mapsize, visblocking, lightmap, range, src, - i + 1, start, slope_l, xx, xy, yx, yy); - new_start = slope_r; - } - } - - if (blocked) break; - } -} - -/* http://www.roguebasin.com/index.php?title=FOV_using_recursive_shadowcasting - */ -void fov_shadowcast(const void* map, const ivec2 mapsize, - bool (*visblocking)(const void*), i32* lightmap, - const i32 range, const ivec2 src) { - - const i8 m[4][8] = { - {1, 0, 0, -1, -1, 0, 0, 1}, - {0, 1, -1, 0, 0, -1, 1, 0}, - {0, 1, 1, 0, 0, -1, -1, 0}, - {1, 0, 0, 1, -1, 0, 0, -1}, - }; - - for (i32 oct = 0; oct < 8; oct++) { - fov_shadowcast_rec(map, mapsize, visblocking, lightmap, range, src, 1, 1.0, - 0.0, m[0][oct], m[1][oct], m[2][oct], m[3][oct]); - } - - /* The center is the most lit square */ - lightmap[src[1] * mapsize[0] + src[0]] = range; -} diff --git a/src/utils/src/hashmap.c b/src/utils/src/hashmap.c deleted file mode 100644 index f7784d5..0000000 --- a/src/utils/src/hashmap.c +++ /dev/null @@ -1,5 +0,0 @@ -#include <engine/utils/hashmap.h> - -/* Currently, this is a "works, but very poorly" placeholder implementation. - * Should be avoided in practice */ -usize lolhash(const usize s, usize v) { return v % s; } diff --git a/src/utils/src/misc.c b/src/utils/src/misc.c deleted file mode 100644 index 063efbf..0000000 --- a/src/utils/src/misc.c +++ /dev/null @@ -1,86 +0,0 @@ -#include <stdint.h> -#include <stdlib.h> - -#include <string.h> - -#include <engine/core/logging.h> -#include <engine/utils.h> - -/* These should all be in some external facing module "tools" */ - -f32 lerp(f32 dt, f32 a, f32 b) { return (a * (1.0f - dt)) + (b * dt); } - -i32 int_lerp(f32 dt, i32 a, i32 b) { - return (i32)((f32)a * (1.0f - dt)) + (i32)((f32)b * dt); -} - -u32 hash(char* str) { - u32 sum = 0; - while (*str != '\0') { - sum ^= (u32)(*str) * 0xdeece66d + 0xb; - str++; - } - return sum; -} - -/* Populates dstmap - * on success: return pointer to dstmap - * on failure: return NULL */ -i32* kernmap(const void* map, i32* dstmap, const ivec2 mapsize, - predicate_t* predicate) { - const usize w = (usize)mapsize[0]; - const usize h = (usize)mapsize[1]; - i32 mask[w * h]; - - if (w * h < 1) return NULL; - - for (usize i = 0; i < w * h; i++) { - mask[i] = predicate((void*)((u64)map + sizeof(i32) * i)) ? 1 : 0; - } - - for (usize y = 1; y < h - 1; y++) { - for (usize x = 1; x < w - 1; x++) { - const usize global_idx = (y * w) + x; - const usize offs = global_idx - w - 1; - i32 _sum = 0; - - i32 shift = 0; - - /* We go in the following order */ - /* ....|0|1|2|....*/ - /* ....|3|4|5|....*/ - /* ....|6|7|8|....*/ - /* Where `4` is in the center, MASK_C */ - for (usize yy = offs; yy <= offs + w + w; yy += w) { - for (usize xx = yy; xx < yy + 3; xx++) { - _sum = _sum | (mask[xx] << shift++); - } - } - - dstmap[global_idx] = _sum; - } - } - return dstmap; -} - -/* Returns an index from the given weights. */ -i32 pick_from_sample(const i32* weights, i32 len) { - if (len <= 0) return 0; - - /* Cumulative sum */ - i32 cumweights[len]; - i32 sum = 0; - for (i32 i = 0; i < len; i++) { - sum += weights[i]; - cumweights[i] = sum; - } - - if (sum == 0) return 0; - - i32 pick = rand() % sum; - - for (i32 i = 0; i < len; i++) { - if (pick < cumweights[i]) return i; - } - return -1; -} diff --git a/src/utils/src/stack.c b/src/utils/src/stack.c deleted file mode 100644 index a7cb16d..0000000 --- a/src/utils/src/stack.c +++ /dev/null @@ -1,82 +0,0 @@ -#include <engine/core/logging.h> -#include <engine/utils/stack.h> -#include <stdlib.h> - -Stack stack_new_ex(const usize element_size, const usize size) { - Stack s = { - .head = 0, - .elem_size = element_size, - .size = element_size * size, - .chunk_size = element_size * size, - .data = NULL, - }; - - s.data = (void*)calloc(element_size, size); - return s; -} - -Stack stack_new(const usize element_size) { - return stack_new_ex(element_size, 512); -} - -void stack_free(Stack* s) { - if (s->data == NULL) return; - free(s->data); - s->data = NULL; -} - -void* stack_pop(Stack* s) { - if (s->head == 0) return NULL; /* Empty stack */ - return (u8*)s->data + (--(s->head) * s->elem_size); -} - -void stack_push(Stack* s, void* elem) { - if (elem == NULL) { - WARN("%s received a nullptr", __func__); - return; - } - if (s->head > 0 && s->head * s->elem_size >= s->size) { - WARN("Allocating more stack memory"); - /* Reallocate more memory and update size */ - void* ptr = realloc(s->data, s->size + s->chunk_size); - if (ptr == NULL) { - ERROR("Failed to resize memory for stack"); - exit(EXIT_FAILURE); - } - s->data = ptr; - // memset((void*)((u64)s->data + (s->size - s->elem_size)), 0, - // s->chunk_size); - s->size += s->chunk_size; - } - memcpy((u8*)s->data + s->head * s->elem_size, elem, s->elem_size); - s->head++; -} - -void* stack_peek(Stack* s) { - if (s->head <= 0) return NULL; /* Empty stack */ - return (u8*)s->data + ((s->head - 1) * s->elem_size); -} - -usize stack_size(const Stack* s) { return s->head; } - -void stack_swap(Stack* s, Stack* t) { - if (s->size > t->size) { - t->data = realloc(t->data, s->size); - } else if (t->size > s->size) { - s->data = realloc(s->data, t->size); - } - void* tmp = malloc(s->size); - if (tmp == NULL) { - ERROR("Failed to allocate memory for stack swapping!"); - exit(EXIT_FAILURE); - } - usize shead = s->head; - - memcpy(tmp, s->data, s->size); - memcpy(s->data, t->data, t->size); - memcpy(t->data, tmp, s->size); - - s->head = t->head; - t->head = shead; - free(tmp); -} |
