diff --git a/README.gmi b/README.gmi index d1b5dd3..815f69f 100644 --- a/README.gmi +++ b/README.gmi @@ -1,7 +1,7 @@ # Simworld Lite Simworld is a zero-player game in which players create simulated environments and ecosystems that run with no user intervention. The environments and the creatures that inhabit them are all completely defined through user-created mods. Though there's no real goal to the game, a good challenge is to create ecosystems that are self-sustaining and can thus run indefinitely. -Note: I'm not galaxy-brained enough to do the full idea at the moment, so this is the "lite" version, contianing only the bare minimum to make the idea work. +Note: I'm not galaxy-brained enough to do the full idea at the moment, so this is the "lite" version, containing only the bare minimum to make the idea work. ## Build from Source ### Dependencies diff --git a/build.sh b/build.sh index ef09b6d..01f931d 100755 --- a/build.sh +++ b/build.sh @@ -29,10 +29,8 @@ mkdir -p build cd build || exit if [ ${debug} -eq 1 ]; then - echo debug cmake -DCMAKE_BUILD_TYPE=debug .. else - echo release cmake -DCMAKE_BUILD_TYPE=release .. fi diff --git a/src/entity/entity.c b/src/entity/entity.c new file mode 100644 index 0000000..7fbfa51 --- /dev/null +++ b/src/entity/entity.c @@ -0,0 +1,13 @@ +// entity/entity.c + +#include + +#include "entity.h" + +void entity_init(struct entity_t *self, size_t id, size_t x, size_t y) { + assert(self != NULL); + + self->id = id; + self->x = x; + self->y = y; +} diff --git a/src/entity/entity.h b/src/entity/entity.h new file mode 100644 index 0000000..d3042d2 --- /dev/null +++ b/src/entity/entity.h @@ -0,0 +1,14 @@ +#ifndef ENTITY_ENTITY_H +#define ENTITY_ENTITY_H + +#include + +struct entity_t { + size_t id; + size_t x; + size_t y; +}; + +void entity_init(struct entity_t *, size_t, size_t, size_t); + +#endif diff --git a/src/entity/registry.c b/src/entity/registry.c new file mode 100644 index 0000000..af9d175 --- /dev/null +++ b/src/entity/registry.c @@ -0,0 +1,79 @@ +// entity/registry.c + +#include +#include + +#include "registry.h" + +#define MAX_NAME_LENGTH 32 + +enum error_t entity_registrant_init( + struct entity_registrant_t *self, + const char *name, char tile +) { + assert(self != NULL); + + if (name == NULL || strlen(name) > MAX_NAME_LENGTH) return ERR_INPUT; + + const char *dup = strndup(name, MAX_NAME_LENGTH); + if (dup == NULL) return ERR_ALLOC; + + self->name = dup; + self->tile = tile; + + return ERR_OK; +} + +void entity_registrant_free(struct entity_registrant_t *self) { + assert (self != NULL); + + free((void *)self->name); +} + + +enum error_t entity_registry_init(struct entity_registry_t *self) { + assert(self != NULL); + + self->size = 1; + + struct entity_registrant_t *entities = calloc( + self->size, sizeof(struct entity_registrant_t) + ); + + if (entities == NULL) return ERR_ALLOC; + + struct entity_registrant_t null_entity; + entity_registrant_init(&null_entity, "NULL", '0'); + + entities[0] = null_entity; + + self->entities = entities; + return ERR_OK; +} + +void entity_registry_free(struct entity_registry_t *self) { + assert(self != NULL); + + for (size_t i = 0; i < self->size; i++) + entity_registrant_free(&self->entities[i]); + + free(self->entities); +} + +enum error_t entity_registry_append( + struct entity_registry_t *self, + struct entity_registrant_t *registrant +) { + assert(self != NULL && registrant != NULL); + + self->size += 1; + self->entities = reallocarray( + self->entities, self->size, + sizeof(struct entity_registrant_t) + ); + + if (self->entities == NULL) return ERR_ALLOC; + + self->entities[self->size - 1] = *registrant; + return ERR_OK; +} diff --git a/src/entity/registry.h b/src/entity/registry.h new file mode 100644 index 0000000..9cadf8b --- /dev/null +++ b/src/entity/registry.h @@ -0,0 +1,34 @@ +#ifndef ENTITY_REGISTRY_H +#define ENTITY_REGISTRY_H + +#include + +#include "../error.h" + +struct entity_registrant_t { + const char *name; + char tile; +}; + +enum error_t entity_registrant_init( + struct entity_registrant_t *, + const char *, char +); + +void entity_registrant_free(struct entity_registrant_t *); + + +struct entity_registry_t { + struct entity_registrant_t *entities; + size_t size; +}; + +enum error_t entity_registry_init(struct entity_registry_t *); +void entity_registry_free(struct entity_registry_t *); + +enum error_t entity_registry_append( + struct entity_registry_t *, + struct entity_registrant_t * +); + +#endif diff --git a/src/error.c b/src/error.c new file mode 100644 index 0000000..5a6e401 --- /dev/null +++ b/src/error.c @@ -0,0 +1,15 @@ +// error.c + +#include "error.h" + +const char *ERROR_STRS[] = { + "SUCCESS", + "BAD INPUT", + "ALLOCATION", + "NOT FOUND", +}; + +_Static_assert( + __ERR_COUNT == (sizeof(ERROR_STRS) / sizeof(ERROR_STRS[0])), + "len(ERROR_STRS) must match __ERR_COUNT" +); diff --git a/src/error.h b/src/error.h new file mode 100644 index 0000000..7ffbda8 --- /dev/null +++ b/src/error.h @@ -0,0 +1,14 @@ +#ifndef ERROR_H +#define ERROR_H + +enum error_t { + ERR_OK, + ERR_INPUT, + ERR_ALLOC, + ERR_NOTFOUND, + __ERR_COUNT, +}; + +extern const char *ERROR_STRS[]; + +#endif diff --git a/src/main.c b/src/main.c index ab3a851..823a35a 100644 --- a/src/main.c +++ b/src/main.c @@ -2,7 +2,29 @@ #include +#include "world.h" + int main(void) { - puts("Hello, world!"); + enum error_t err = ERR_OK; + + struct world_t world; + err = world_init(&world, 10, 10); + if (err != ERR_OK) goto error; + + err = world_register_entity(&world, "john", 'j'); + if (err != ERR_OK) goto error_register; + + err = world_place_entity(&world, 1, 1, 2); + if (err != ERR_OK) goto error_register; + + world_print(&world); + + world_free(&world); return 0; + +error_register: + world_free(&world); +error: + printf("ERROR: %s", ERROR_STRS[err]); + exit(err); } diff --git a/src/world.c b/src/world.c new file mode 100644 index 0000000..0c08c9d --- /dev/null +++ b/src/world.c @@ -0,0 +1,79 @@ +// world.c + +#include +#include + +#include "world.h" + +enum error_t world_init(struct world_t *self, size_t height, size_t width) { + assert(self != NULL); + + self->height = height; + self->width = width; + + memset(self->entities, 0, MAX_ENTITIES * sizeof(struct entity_t)); + + enum error_t err = entity_registry_init(&self->registered_entities); + if (err != ERR_OK) return err; + + return ERR_OK; +} + +void world_free(struct world_t *self) { + entity_registry_free(&self->registered_entities); +} + +enum error_t world_register_entity( + struct world_t *self, + const char *name, char tile +) { + enum error_t err; + struct entity_registry_t *registry = &self->registered_entities; + + struct entity_registrant_t registrant; + err = entity_registrant_init(®istrant, name, tile); + if (err != ERR_OK) return err; + + err = entity_registry_append(registry, ®istrant); + if (err != ERR_OK) return err; + + return ERR_OK; +} + +static size_t world_find_empty_entity(struct world_t *self) { + for (size_t i = 0; i < MAX_ENTITIES; i++) + if (self->entities[i].id == 0) return i; + + return MAX_ENTITIES; +} + +enum error_t world_place_entity( + struct world_t *self, + size_t id, size_t x, size_t y +) { + assert(self != NULL); + + size_t i = world_find_empty_entity(self); + if (i == MAX_ENTITIES) return ERR_NOTFOUND; + + entity_init(&self->entities[i], id, x, y); + + return ERR_OK; +} + +#include +void world_print(struct world_t *self) { + for (size_t i = 0; i < MAX_ENTITIES; i++) { + struct entity_t *entity = &self->entities[i]; + struct entity_registrant_t *registrant = + &self->registered_entities.entities[entity->id]; + + if (entity->id == 0) continue; + + printf("%zu (%s): (%zu,%zu) '%c'\n", + entity->id, registrant->name, + entity->x, entity->y, + registrant->tile + ); + } +} diff --git a/src/world.h b/src/world.h new file mode 100644 index 0000000..d855d12 --- /dev/null +++ b/src/world.h @@ -0,0 +1,28 @@ +#ifndef WORLD_H +#define WORLD_H + +#include + +#include "error.h" +#include "entity/registry.h" +#include "entity/entity.h" + +#define MAX_ENTITIES 256 + +struct world_t { + struct entity_t entities[MAX_ENTITIES]; + struct entity_registry_t registered_entities; + + size_t height; + size_t width; +}; + +enum error_t world_init(struct world_t *, size_t, size_t); +void world_free(struct world_t *); + +enum error_t world_register_entity(struct world_t *, const char *, char); +enum error_t world_place_entity(struct world_t *, size_t, size_t, size_t); + +void world_print(struct world_t *); + +#endif