Moved code and assets for the game to a seperate folder. Moved jansson and raylib to third_party.
This commit is contained in:
43
src/game/shared/entity.h
Normal file
43
src/game/shared/entity.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef ENTITY_H
|
||||
#define ENTITY_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef uint16_t Entity_ID;
|
||||
|
||||
#define INVALID_ENTITY_ID (Entity_ID)65535
|
||||
|
||||
typedef enum {
|
||||
Entity_Movement_Direction_None,
|
||||
Entity_Movement_Direction_Up,
|
||||
Entity_Movement_Direction_Down,
|
||||
Entity_Movement_Direction_Right,
|
||||
Entity_Movement_Direction_Left,
|
||||
} Entity_Movement_Direction;
|
||||
|
||||
typedef enum {
|
||||
Entity_Type_Snake_Head,
|
||||
Entity_Type_Snake_Body,
|
||||
Entity_Type_Food,
|
||||
} Entity_Type;
|
||||
|
||||
typedef struct {
|
||||
bool active;
|
||||
|
||||
// TODO: SS - Maybe add an ID here.
|
||||
|
||||
Entity_Type type;
|
||||
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
|
||||
uint16_t prev_x;
|
||||
uint16_t prev_y;
|
||||
|
||||
Entity_Movement_Direction move_direction;
|
||||
|
||||
Entity_ID child;
|
||||
} Entity;
|
||||
|
||||
#endif
|
||||
118
src/game/shared/game_world.c
Normal file
118
src/game/shared/game_world.c
Normal file
@@ -0,0 +1,118 @@
|
||||
#include "game_world.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define MIN_LEVEL_WIDTH 8 // TODO: SS - Move these out of here.
|
||||
#define MIN_LEVEL_HEIGHT 8
|
||||
|
||||
Game_World *game_world_create(uint32_t seed, uint16_t level_width, uint16_t level_height) {
|
||||
assert(level_width >= MIN_LEVEL_WIDTH); // We should probably have failed earlier.
|
||||
assert(level_height >= MIN_LEVEL_HEIGHT);
|
||||
|
||||
Game_World *w = (Game_World *)calloc(1, sizeof(Game_World));
|
||||
assert(w != NULL);
|
||||
w->seed = seed;
|
||||
random_init(&w->random_generator, w->seed);
|
||||
|
||||
w->max_entities = level_width * level_height;
|
||||
w->entities = (Entity *)calloc(w->max_entities, sizeof(Entity));
|
||||
|
||||
// Set up entity-id queue.
|
||||
assert(squeue_init(&w->entity_id_queue, w->max_entities, sizeof(Entity_ID)));
|
||||
for(uint16_t i = 0; i < w->entity_id_queue.capacity; i++) {
|
||||
Entity_ID id = (Entity_ID)i;
|
||||
assert(squeue_push(&w->entity_id_queue, &id));
|
||||
}
|
||||
|
||||
grid_initialize(&w->grid, level_width, level_height);
|
||||
|
||||
{ // TEMP: SS - Testing ..
|
||||
for(uint16_t i = 0; i < 8; i++) {
|
||||
Entity_ID entity_food;
|
||||
assert(game_world_create_entity(
|
||||
w,
|
||||
Entity_Type_Food,
|
||||
(uint16_t)random_u32_range(&w->random_generator, 0, level_width),
|
||||
(uint16_t)random_u32_range(&w->random_generator, 0, level_height),
|
||||
&entity_food
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
void game_world_destroy(Game_World *world) {
|
||||
assert(world != NULL);
|
||||
|
||||
world->seed = 0;
|
||||
world->max_entities = 0;
|
||||
free(world->entities);
|
||||
grid_dispose(&world->grid);
|
||||
squeue_free(&world->entity_id_queue);
|
||||
|
||||
free(world);
|
||||
}
|
||||
|
||||
bool game_world_create_entity(Game_World *world, Entity_Type type, uint16_t x, uint16_t y, Entity_ID *out_entity_id) {
|
||||
assert(world != NULL);
|
||||
|
||||
*out_entity_id = INVALID_ENTITY_ID;
|
||||
|
||||
if(x >= world->grid.width) {
|
||||
printf("Failed to create entity; Invalid x-coordinate.\n");
|
||||
return false;
|
||||
}
|
||||
if(y >= world->grid.height) {
|
||||
printf("Failed to create entity; Invalid y-coordinate.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
Entity_ID id = 0;
|
||||
if(!squeue_pop(&world->entity_id_queue, (void *)&id)) {
|
||||
printf("No free entity ids.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
world->entities[id] = (Entity) {
|
||||
.active = true,
|
||||
.type = type,
|
||||
.child = INVALID_ENTITY_ID
|
||||
};
|
||||
|
||||
Grid_Cell *cell = grid_get_cell(&world->grid, x, y); // TEMP: SS - Hardcoded coordinates. // TODO: SS - Find good coordinate.
|
||||
assert(cell != NULL);
|
||||
assert(grid_try_add_entity_to_cell(cell, &world->entities[id]));
|
||||
|
||||
*out_entity_id = id;
|
||||
return true;
|
||||
}
|
||||
|
||||
void game_world_destroy_entity(Game_World *world, Entity_ID entity_id) {
|
||||
assert(world != NULL);
|
||||
|
||||
Entity *entity = game_world_try_get_entity_by_id(
|
||||
world,
|
||||
entity_id
|
||||
);
|
||||
assert(entity != NULL);
|
||||
entity->active = false;
|
||||
|
||||
Grid_Cell *cell = grid_get_cell(&world->grid, entity->x, entity->y);
|
||||
assert(cell != NULL);
|
||||
assert(grid_try_remove_entity_from_cell(cell));
|
||||
|
||||
squeue_push(&world->entity_id_queue, (void *)&entity_id);
|
||||
}
|
||||
|
||||
Entity *game_world_try_get_entity_by_id(Game_World *world, Entity_ID id) {
|
||||
assert(world != NULL);
|
||||
|
||||
if(id >= world->max_entities) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &world->entities[id];
|
||||
}
|
||||
32
src/game/shared/game_world.h
Normal file
32
src/game/shared/game_world.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef WORLD_H
|
||||
#define WORLD_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "entity.h"
|
||||
#include "grid.h"
|
||||
#include "shared/squeue.h"
|
||||
#include "shared/random.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t seed;
|
||||
Random_Generator random_generator;
|
||||
|
||||
SQueue entity_id_queue;
|
||||
Entity *entities;
|
||||
uint16_t max_entities;
|
||||
|
||||
Grid grid;
|
||||
|
||||
} Game_World;
|
||||
|
||||
Game_World *game_world_create(uint32_t seed, uint16_t level_width, uint16_t level_height);
|
||||
void game_world_destroy(Game_World *world);
|
||||
|
||||
bool game_world_create_entity(Game_World *world, Entity_Type type, uint16_t x, uint16_t y, Entity_ID *out_entity_id);
|
||||
void game_world_destroy_entity(Game_World *world, Entity_ID entity_id);
|
||||
|
||||
// TODO: SS - "void game_world_spawn_player(Game_World *world, ..)"
|
||||
|
||||
Entity *game_world_try_get_entity_by_id(Game_World *world, Entity_ID id);
|
||||
|
||||
#endif
|
||||
126
src/game/shared/grid.c
Normal file
126
src/game/shared/grid.c
Normal file
@@ -0,0 +1,126 @@
|
||||
#include "grid.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define GRID_MIN_WIDTH 8
|
||||
#define GRID_MIN_HEIGHT 8
|
||||
|
||||
static bool from_grid_index(Grid *grid, uint16_t grid_index, uint16_t *out_x, uint16_t *out_y) {
|
||||
assert(grid != NULL);
|
||||
assert(out_x != NULL);
|
||||
assert(out_y != NULL);
|
||||
|
||||
if (!grid || !out_x || !out_y) return false;
|
||||
if (grid_index >= grid->width * grid->height) return false;
|
||||
|
||||
*out_x = grid_index % grid->width;
|
||||
*out_y = grid_index / grid->width;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool grid_initialize(Grid *grid, uint16_t width, uint16_t height) {
|
||||
assert(grid != NULL);
|
||||
|
||||
if(width < GRID_MIN_WIDTH || height < GRID_MIN_HEIGHT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
grid->width = width;
|
||||
grid->height = height;
|
||||
grid->cells = calloc(width * height, sizeof(Grid_Cell));
|
||||
|
||||
for(uint16_t i = 0; i < (width * height); i++) {
|
||||
Grid_Cell *cell = &grid->cells[i];
|
||||
assert(from_grid_index(grid, i, &cell->x, &cell->y));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void grid_dispose(Grid *grid) {
|
||||
assert(grid != NULL);
|
||||
|
||||
free(grid->cells);
|
||||
memset(grid, 0, sizeof(Grid));
|
||||
}
|
||||
|
||||
static bool to_grid_index(Grid *grid, uint16_t x, uint16_t y, uint16_t *out_grid_index) {
|
||||
assert(grid != NULL);
|
||||
assert(out_grid_index != NULL);
|
||||
|
||||
if(!grid || !out_grid_index) {
|
||||
return false;
|
||||
}
|
||||
if(x >= grid->width || y >= grid->height) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*out_grid_index = y * grid->width + x;
|
||||
return true;
|
||||
}
|
||||
|
||||
Grid_Cell *grid_get_cell(Grid *grid, uint16_t x, uint16_t y) {
|
||||
assert(grid != NULL);
|
||||
if(x >= grid->width || y >= grid->height) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint16_t grid_index = 0;
|
||||
if(!to_grid_index(grid, x, y, &grid_index)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &grid->cells[grid_index];
|
||||
}
|
||||
|
||||
bool grid_try_add_entity_to_cell(Grid_Cell *cell, Entity *entity) {
|
||||
assert(cell != NULL);
|
||||
assert(entity != NULL);
|
||||
|
||||
// TODO: SS - Could check what type of cell it is to determine if
|
||||
// we're allowed to place an entity here. Is it a wall? Lava?
|
||||
|
||||
if(cell->entity != NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cell->entity = entity;
|
||||
entity->x = cell->x;
|
||||
entity->y = cell->y;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool grid_try_remove_entity_from_cell(Grid_Cell *cell) {
|
||||
assert(cell != NULL);
|
||||
|
||||
if(cell->entity == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cell->entity->x = 0;
|
||||
cell->entity->y = 0;
|
||||
cell->entity = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void grid_move_entity_from_cell_to_cell(Grid_Cell *cell_a, Grid_Cell *cell_b) {
|
||||
assert(cell_a != NULL);
|
||||
assert(cell_b != NULL);
|
||||
|
||||
assert(cell_a->entity != NULL); // We expect cell A to have an Entity to move.
|
||||
assert(cell_b->entity == NULL); // We expect cell B to NOT have an Entity.
|
||||
|
||||
Entity *entity_to_be_moved = cell_a->entity;
|
||||
|
||||
uint16_t start_x = cell_a->x;
|
||||
uint16_t start_y = cell_a->y;
|
||||
|
||||
assert(grid_try_remove_entity_from_cell(cell_a));
|
||||
assert(grid_try_add_entity_to_cell(cell_b, entity_to_be_moved));
|
||||
|
||||
entity_to_be_moved->prev_x = start_x;
|
||||
entity_to_be_moved->prev_y = start_y;
|
||||
}
|
||||
33
src/game/shared/grid.h
Normal file
33
src/game/shared/grid.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef GRID_H
|
||||
#define GRID_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "entity.h"
|
||||
|
||||
typedef struct {
|
||||
Entity *entity;
|
||||
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
} Grid_Cell;
|
||||
|
||||
typedef struct {
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
|
||||
Grid_Cell *cells;
|
||||
} Grid;
|
||||
|
||||
bool grid_initialize(Grid *grid, uint16_t width, uint16_t height);
|
||||
void grid_dispose(Grid *grid);
|
||||
|
||||
Grid_Cell *grid_get_cell(Grid *grid, uint16_t x, uint16_t y);
|
||||
|
||||
bool grid_try_add_entity_to_cell(Grid_Cell *cell, Entity *entity);
|
||||
bool grid_try_remove_entity_from_cell(Grid_Cell *cell);
|
||||
|
||||
void grid_move_entity_from_cell_to_cell(Grid_Cell *cell_a, Grid_Cell *cell_b);
|
||||
|
||||
#endif
|
||||
193
src/game/shared/map.c
Normal file
193
src/game/shared/map.c
Normal file
@@ -0,0 +1,193 @@
|
||||
/**
|
||||
* Copyright (c) 2014 rxi
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "map.h"
|
||||
|
||||
struct map_node_t {
|
||||
unsigned hash;
|
||||
void *value;
|
||||
map_node_t *next;
|
||||
/* char key[]; */
|
||||
/* char value[]; */
|
||||
};
|
||||
|
||||
|
||||
static unsigned map_hash(const char *str) {
|
||||
unsigned hash = 5381;
|
||||
while (*str) {
|
||||
hash = ((hash << 5) + hash) ^ *str++;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
static map_node_t *map_newnode(const char *key, void *value, int vsize) {
|
||||
map_node_t *node;
|
||||
int ksize = strlen(key) + 1;
|
||||
int voffset = ksize + ((sizeof(void*) - ksize) % sizeof(void*));
|
||||
node = malloc(sizeof(*node) + voffset + vsize);
|
||||
if (!node) return NULL;
|
||||
memcpy(node + 1, key, ksize);
|
||||
node->hash = map_hash(key);
|
||||
node->value = ((char*) (node + 1)) + voffset;
|
||||
memcpy(node->value, value, vsize);
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
static int map_bucketidx(map_base_t *m, unsigned hash) {
|
||||
/* If the implementation is changed to allow a non-power-of-2 bucket count,
|
||||
* the line below should be changed to use mod instead of AND */
|
||||
return hash & (m->nbuckets - 1);
|
||||
}
|
||||
|
||||
|
||||
static void map_addnode(map_base_t *m, map_node_t *node) {
|
||||
int n = map_bucketidx(m, node->hash);
|
||||
node->next = m->buckets[n];
|
||||
m->buckets[n] = node;
|
||||
}
|
||||
|
||||
|
||||
static int map_resize(map_base_t *m, int nbuckets) {
|
||||
map_node_t *nodes, *node, *next;
|
||||
map_node_t **buckets;
|
||||
int i;
|
||||
/* Chain all nodes together */
|
||||
nodes = NULL;
|
||||
i = m->nbuckets;
|
||||
while (i--) {
|
||||
node = (m->buckets)[i];
|
||||
while (node) {
|
||||
next = node->next;
|
||||
node->next = nodes;
|
||||
nodes = node;
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
/* Reset buckets */
|
||||
buckets = realloc(m->buckets, sizeof(*m->buckets) * nbuckets);
|
||||
if (buckets != NULL) {
|
||||
m->buckets = buckets;
|
||||
m->nbuckets = nbuckets;
|
||||
}
|
||||
if (m->buckets) {
|
||||
memset(m->buckets, 0, sizeof(*m->buckets) * m->nbuckets);
|
||||
/* Re-add nodes to buckets */
|
||||
node = nodes;
|
||||
while (node) {
|
||||
next = node->next;
|
||||
map_addnode(m, node);
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
/* Return error code if realloc() failed */
|
||||
return (buckets == NULL) ? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
static map_node_t **map_getref(map_base_t *m, const char *key) {
|
||||
unsigned hash = map_hash(key);
|
||||
map_node_t **next;
|
||||
if (m->nbuckets > 0) {
|
||||
next = &m->buckets[map_bucketidx(m, hash)];
|
||||
while (*next) {
|
||||
if ((*next)->hash == hash && !strcmp((char*) (*next + 1), key)) {
|
||||
return next;
|
||||
}
|
||||
next = &(*next)->next;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void map_deinit_(map_base_t *m) {
|
||||
map_node_t *next, *node;
|
||||
int i;
|
||||
i = m->nbuckets;
|
||||
while (i--) {
|
||||
node = m->buckets[i];
|
||||
while (node) {
|
||||
next = node->next;
|
||||
free(node);
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
free(m->buckets);
|
||||
}
|
||||
|
||||
|
||||
void *map_get_(map_base_t *m, const char *key) {
|
||||
map_node_t **next = map_getref(m, key);
|
||||
return next ? (*next)->value : NULL;
|
||||
}
|
||||
|
||||
|
||||
int map_set_(map_base_t *m, const char *key, void *value, int vsize) {
|
||||
int n, err;
|
||||
map_node_t **next, *node;
|
||||
/* Find & replace existing node */
|
||||
next = map_getref(m, key);
|
||||
if (next) {
|
||||
memcpy((*next)->value, value, vsize);
|
||||
return 0;
|
||||
}
|
||||
/* Add new node */
|
||||
node = map_newnode(key, value, vsize);
|
||||
if (node == NULL) goto fail;
|
||||
if (m->nnodes >= m->nbuckets) {
|
||||
n = (m->nbuckets > 0) ? (m->nbuckets << 1) : 1;
|
||||
err = map_resize(m, n);
|
||||
if (err) goto fail;
|
||||
}
|
||||
map_addnode(m, node);
|
||||
m->nnodes++;
|
||||
return 0;
|
||||
fail:
|
||||
if (node) free(node);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void map_remove_(map_base_t *m, const char *key) {
|
||||
map_node_t *node;
|
||||
map_node_t **next = map_getref(m, key);
|
||||
if (next) {
|
||||
node = *next;
|
||||
*next = (*next)->next;
|
||||
free(node);
|
||||
m->nnodes--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
map_iter_t map_iter_(void) {
|
||||
map_iter_t iter;
|
||||
iter.bucketidx = -1;
|
||||
iter.node = NULL;
|
||||
return iter;
|
||||
}
|
||||
|
||||
|
||||
const char *map_next_(map_base_t *m, map_iter_t *iter) {
|
||||
if (iter->node) {
|
||||
iter->node = iter->node->next;
|
||||
if (iter->node == NULL) goto nextBucket;
|
||||
} else {
|
||||
nextBucket:
|
||||
do {
|
||||
if (++iter->bucketidx >= m->nbuckets) {
|
||||
return NULL;
|
||||
}
|
||||
iter->node = m->buckets[iter->bucketidx];
|
||||
} while (iter->node == NULL);
|
||||
}
|
||||
return (char*) (iter->node + 1);
|
||||
}
|
||||
78
src/game/shared/map.h
Normal file
78
src/game/shared/map.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Copyright (c) 2014 rxi
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#ifndef MAP_H
|
||||
#define MAP_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define MAP_VERSION "0.1.0"
|
||||
|
||||
struct map_node_t;
|
||||
typedef struct map_node_t map_node_t;
|
||||
|
||||
typedef struct {
|
||||
map_node_t **buckets;
|
||||
unsigned nbuckets, nnodes;
|
||||
} map_base_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned bucketidx;
|
||||
map_node_t *node;
|
||||
} map_iter_t;
|
||||
|
||||
|
||||
#define map_t(T)\
|
||||
struct { map_base_t base; T *ref; T tmp; }
|
||||
|
||||
|
||||
#define map_init(m)\
|
||||
memset(m, 0, sizeof(*(m)))
|
||||
|
||||
|
||||
#define map_deinit(m)\
|
||||
map_deinit_(&(m)->base)
|
||||
|
||||
|
||||
#define map_get(m, key)\
|
||||
( (m)->ref = map_get_(&(m)->base, key) )
|
||||
|
||||
|
||||
#define map_set(m, key, value)\
|
||||
( (m)->tmp = (value),\
|
||||
map_set_(&(m)->base, key, &(m)->tmp, sizeof((m)->tmp)) )
|
||||
|
||||
|
||||
#define map_remove(m, key)\
|
||||
map_remove_(&(m)->base, key)
|
||||
|
||||
|
||||
#define map_iter(m)\
|
||||
map_iter_()
|
||||
|
||||
|
||||
#define map_next(m, iter)\
|
||||
map_next_(&(m)->base, iter)
|
||||
|
||||
|
||||
void map_deinit_(map_base_t *m);
|
||||
void *map_get_(map_base_t *m, const char *key);
|
||||
int map_set_(map_base_t *m, const char *key, void *value, int vsize);
|
||||
void map_remove_(map_base_t *m, const char *key);
|
||||
map_iter_t map_iter_(void);
|
||||
const char *map_next_(map_base_t *m, map_iter_t *iter);
|
||||
|
||||
|
||||
typedef map_t(void*) map_void_t;
|
||||
typedef map_t(char*) map_str_t;
|
||||
typedef map_t(int) map_int_t;
|
||||
typedef map_t(unsigned int) map_uint_t;
|
||||
typedef map_t(char) map_char_t;
|
||||
typedef map_t(float) map_float_t;
|
||||
typedef map_t(double) map_double_t;
|
||||
|
||||
#endif
|
||||
25
src/game/shared/random.c
Normal file
25
src/game/shared/random.c
Normal file
@@ -0,0 +1,25 @@
|
||||
#include "random.h"
|
||||
|
||||
void random_init(Random_Generator *random_generator, uint32_t seed) {
|
||||
if(seed == 0) {
|
||||
seed = 1;
|
||||
}
|
||||
random_generator->seed = seed;
|
||||
random_generator->state = random_generator->seed;
|
||||
}
|
||||
|
||||
uint32_t random_u32(Random_Generator *random_generator) {
|
||||
uint32_t x = random_generator->state;
|
||||
|
||||
x ^= x << 13;
|
||||
x ^= x >> 17;
|
||||
x ^= x << 5;
|
||||
|
||||
random_generator->state = x;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
uint32_t random_u32_range(Random_Generator *random_generator, uint32_t min, uint32_t max) {
|
||||
return min + (random_u32(random_generator) % (max - min + 1));
|
||||
}
|
||||
17
src/game/shared/random.h
Normal file
17
src/game/shared/random.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef RANDOM_H
|
||||
#define RANDOM_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t seed;
|
||||
uint32_t state;
|
||||
} Random_Generator;
|
||||
|
||||
void random_init(Random_Generator *random_generator, uint32_t seed);
|
||||
|
||||
uint32_t random_u32(Random_Generator *random_generator);
|
||||
uint32_t random_u32_range(Random_Generator *random_generator, uint32_t min, uint32_t max);
|
||||
|
||||
|
||||
#endif
|
||||
57
src/game/shared/squeue.c
Normal file
57
src/game/shared/squeue.c
Normal file
@@ -0,0 +1,57 @@
|
||||
#include "squeue.h"
|
||||
|
||||
bool squeue_init(SQueue *q, uint16_t capacity, size_t element_size) {
|
||||
q->buffer = malloc(element_size * capacity);
|
||||
if (!q->buffer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
q->head = q->tail = q->count = 0;
|
||||
q->capacity = capacity;
|
||||
q->element_size = element_size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void squeue_free(SQueue *q) {
|
||||
free(q->buffer);
|
||||
q->buffer = NULL;
|
||||
q->head = q->tail = q->count = q->capacity = 0;
|
||||
q->element_size = 0;
|
||||
}
|
||||
|
||||
bool squeue_push(SQueue *q, const void *elem) {
|
||||
if (q->count == q->capacity) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void *dest = (uint8_t*)q->buffer + q->tail * q->element_size;
|
||||
memcpy(dest, elem, q->element_size);
|
||||
q->tail = (q->tail + 1) % q->capacity;
|
||||
q->count++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool squeue_pop(SQueue *q, void *out) {
|
||||
if (q->count == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void *src = (uint8_t*)q->buffer + q->head * q->element_size;
|
||||
memcpy(out, src, q->element_size);
|
||||
q->head = (q->head + 1) % q->capacity;
|
||||
q->count--;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool squeue_peek(const SQueue *q, void *out) {
|
||||
if (q->count == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void *src = (uint8_t*)q->buffer + q->head * q->element_size;
|
||||
memcpy(out, src, q->element_size);
|
||||
return true;
|
||||
}
|
||||
27
src/game/shared/squeue.h
Normal file
27
src/game/shared/squeue.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef SQUEUE_H
|
||||
#define SQUEUE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
// FIFO.
|
||||
|
||||
typedef struct {
|
||||
void *buffer;
|
||||
uint16_t head;
|
||||
uint16_t tail;
|
||||
uint16_t count;
|
||||
uint16_t capacity;
|
||||
size_t element_size;
|
||||
} SQueue;
|
||||
|
||||
bool squeue_init(SQueue *q, uint16_t capacity, size_t element_size);
|
||||
void squeue_free(SQueue *q);
|
||||
|
||||
bool squeue_push(SQueue *q, const void *elem);
|
||||
bool squeue_pop(SQueue *q, void *out);
|
||||
bool squeue_peek(const SQueue *q, void *out);
|
||||
|
||||
#endif
|
||||
13
src/game/shared/wang_hash.h
Normal file
13
src/game/shared/wang_hash.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef WANG_HASH_H
|
||||
#define WANG_HASH_H
|
||||
|
||||
static inline uint32_t wang_hash(uint32_t v) {
|
||||
v = (v ^ 61) ^ (v >> 16);
|
||||
v = v + (v << 3);
|
||||
v = v ^ (v >> 4);
|
||||
v = v * 0x27d4eb2d;
|
||||
v = v ^ (v >> 15);
|
||||
return v;
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user