Last active
February 27, 2023 15:25
-
-
Save SanderMertens/cceeea0d209e1c9d4ec30c1bb162ae3d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <c_app.h> | |
#include "flecs.h" | |
#include <stdio.h> | |
#include <stdlib.h> | |
#define STARS (1000) | |
#define PLANETS_MAX (10) | |
#define P_PLANET_WATER (0.1) | |
#define P_PLANET_OIL (0.005) | |
#define P_PLANET_COPPER (0.05) | |
#define P_PLANET_URANIUM (0.01) | |
#define SPACESHIPS (10 * 1000) | |
#define P_FREIGHTER (0.1) | |
#define T_LIQUID_TRANSPORT (0.4) | |
#define T_SOLID_TRANSPORT (0.8) | |
#define T_RADIOACTIVE_TRANSPORT (1.0) | |
#define MEASURE (2.0) | |
typedef struct { | |
float value; | |
} Value; | |
float randf(float max) { | |
return max * (float)rand() / (float)RAND_MAX; | |
} | |
bool chance(float p) { | |
return randf(1.0) > (1.0 - p); | |
} | |
int main(int argc, char* argv[]) | |
{ | |
ecs_world_t *world = ecs_init(); | |
ECS_COMPONENT(world, Value); | |
ecs_struct(world, { | |
.entity = ecs_id(Value), | |
.members = { | |
{ .name = "value", .type = ecs_id(ecs_f32_t) } | |
} | |
}); | |
/* Relationships */ | |
ECS_ENTITY(world, InSystem, (With, ChildOf)); | |
ECS_TAG(world, Has); | |
ECS_TAG(world, Requires); | |
ECS_TAG(world, Faction); | |
/* Celestial bodies */ | |
ECS_TAG(world, Star); | |
ECS_TAG(world, Planet); | |
ECS_TAG(world, Moon); | |
/* Spaceships */ | |
ECS_TAG(world, SpaceShip); | |
ECS_TAG(world, Freighter); | |
ECS_TAG(world, LiquidStorage); | |
ECS_TAG(world, SolidStorage); | |
ECS_TAG(world, RadioActiveStorage); | |
/* Factions */ | |
ECS_TAG(world, Humans); | |
ECS_TAG(world, Dolphins); | |
ECS_TAG(world, Zorgs); | |
/* Resources */ | |
ECS_ENTITY(world, Water, (Requires, LiquidStorage)); | |
ECS_ENTITY(world, Oil, (Requires, LiquidStorage)); | |
ECS_ENTITY(world, Copper, (Requires, SolidStorage)); | |
ECS_ENTITY(world, Uranium, (Requires, RadioActiveStorage)); | |
ecs_set(world, Water, Value, {0.14}); | |
ecs_set(world, Oil, Value, {23}); | |
ecs_set(world, Copper, Value, {1.2}); | |
ecs_set(world, Uranium, Value, {85.7}); | |
int32_t planet_count = 0, freighter_count = 0; | |
ecs_time_t t = {0}; | |
ecs_time_measure(&t); | |
ecs_entity_t *stars = ecs_os_malloc_n(ecs_entity_t, STARS); | |
for (int s = 0; s < STARS; s ++) { | |
stars[s] = ecs_new(world, Star); | |
int planets = randf(PLANETS_MAX); | |
for (int p = 0; p < planets; p ++) { | |
ecs_entity_t planet = ecs_new(world, Planet); | |
ecs_add_pair(world, planet, InSystem, stars[s]); | |
if (chance(P_PLANET_WATER)) { | |
ecs_add_pair(world, planet, Has, Water); | |
} | |
if (chance(P_PLANET_OIL)) { | |
ecs_add_pair(world, planet, Has, Oil); | |
} | |
if (chance(P_PLANET_COPPER)) { | |
ecs_add_pair(world, planet, Has, Copper); | |
} | |
if (chance(P_PLANET_URANIUM)) { | |
ecs_add_pair(world, planet, Has, Uranium); | |
} | |
float faction = randf(1.0); | |
if (faction < 0.33) { | |
ecs_add_pair(world, planet, Faction, Humans); | |
} else if (faction < 0.66) { | |
ecs_add_pair(world, planet, Faction, Dolphins); | |
} else { | |
ecs_add_pair(world, planet, Faction, Zorgs); | |
} | |
planet_count ++; | |
} | |
} | |
ecs_entity_t *spaceships = ecs_os_malloc_n(ecs_entity_t, SPACESHIPS); | |
for (int s = 0; s < SPACESHIPS; s ++) { | |
spaceships[s] = ecs_new(world, SpaceShip); | |
ecs_entity_t star = stars[(int)randf(STARS)]; | |
ecs_add_pair(world, spaceships[s], InSystem, star); | |
if (chance(P_FREIGHTER)) { | |
ecs_add(world, spaceships[s], Freighter); | |
float kind = randf(1.0); | |
if (kind < T_LIQUID_TRANSPORT) { | |
ecs_add_pair(world, spaceships[s], Has, LiquidStorage); | |
} else if (kind < T_SOLID_TRANSPORT) { | |
ecs_add_pair(world, spaceships[s], Has, SolidStorage); | |
} else { | |
ecs_add_pair(world, spaceships[s], Has, RadioActiveStorage); | |
} | |
freighter_count ++; | |
} | |
float faction = randf(1.0); | |
if (faction < 0.33) { | |
ecs_add_pair(world, spaceships[s], Faction, Humans); | |
} else if (faction < 0.66) { | |
ecs_add_pair(world, spaceships[s], Faction, Dolphins); | |
} else { | |
ecs_add_pair(world, spaceships[s], Faction, Zorgs); | |
} | |
} | |
printf("Loaded in %.2fs (stars = %d, planets = %d, spaceships = %d, freighters = %d)\n", | |
ecs_time_measure(&t), | |
STARS, planet_count, SPACESHIPS, freighter_count); | |
// Uncomment to run as a command line app | |
// char cmd[1024]; | |
// while (true) { | |
// printf("?- "); fgets(cmd, 1024, stdin); | |
// ecs_rule_t *r = ecs_rule(world, { | |
// .expr = cmd | |
// }); | |
// if (!r) { | |
// continue; | |
// } | |
// ecs_iter_t it = ecs_rule_iter(world, r); | |
// while (ecs_iter_next(&it)) { | |
// char *str = ecs_iter_str(&it); | |
// printf("%s\n", str); | |
// ecs_os_free(str); | |
// } | |
// char *str = ecs_rule_str(r); | |
// printf("%s\n", str); | |
// ecs_os_free(str); | |
// } | |
const char *q = | |
"Freighter($this), " | |
"InSystem($this, $star), " | |
"InSystem($_planet, $star), " | |
"Planet($_planet), " | |
"Faction($this, $faction), " | |
"Faction($_planet, $faction), " | |
"Has($_planet, $resource), " | |
"Requires($resource, $requires), " | |
"Has($this, $requires), " | |
"Value($resource)" | |
; | |
ecs_rule_t *r = ecs_rule(world, { | |
.entity = ecs_entity(world, { .name = "resource_transports" }), | |
.expr = q, | |
}); | |
int32_t iter = 0, count = 0; | |
ecs_time_measure(&t); | |
ecs_time_t start = t; | |
while (true) { | |
ecs_iter_t it = ecs_rule_iter(world, r); | |
while (ecs_rule_next(&it)) { | |
count += it.count; | |
} | |
iter ++; | |
if (!(iter % 100)) { | |
ecs_time_t tt = start; | |
if (ecs_time_measure(&tt) > MEASURE) { | |
break; | |
} | |
} | |
} | |
printf("query takes %.3f ms (%d found)\n", | |
(ecs_time_measure(&t) / (float)iter) * 1000, | |
count / iter); | |
// Prints profile in debug mode | |
ecs_iter_t it = ecs_rule_iter(world, r); | |
it.flags |= EcsIterProfile; | |
while (ecs_rule_next(&it)) { | |
count += it.count; | |
} | |
return ecs_app_run(world, &(ecs_app_desc_t) { | |
.enable_rest = true, | |
.target_fps = 60 | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment