register entity types and place them in world

This commit is contained in:
snit 2024-09-28 18:13:42 -05:00
parent d9967ceeae
commit 78cd50a7f4
11 changed files with 300 additions and 4 deletions

View File

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

View File

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

13
src/entity/entity.c Normal file
View File

@ -0,0 +1,13 @@
// entity/entity.c
#include <assert.h>
#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;
}

14
src/entity/entity.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef ENTITY_ENTITY_H
#define ENTITY_ENTITY_H
#include <stdlib.h>
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

79
src/entity/registry.c Normal file
View File

@ -0,0 +1,79 @@
// entity/registry.c
#include <assert.h>
#include <string.h>
#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;
}

34
src/entity/registry.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef ENTITY_REGISTRY_H
#define ENTITY_REGISTRY_H
#include <stdlib.h>
#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

15
src/error.c Normal file
View File

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

14
src/error.h Normal file
View File

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

View File

@ -2,7 +2,29 @@
#include <stdio.h>
#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);
}

79
src/world.c Normal file
View File

@ -0,0 +1,79 @@
// world.c
#include <assert.h>
#include <string.h>
#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(&registrant, name, tile);
if (err != ERR_OK) return err;
err = entity_registry_append(registry, &registrant);
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 <stdio.h>
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
);
}
}

28
src/world.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef WORLD_H
#define WORLD_H
#include <stdlib.h>
#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