changeset 261:bfde372bf152

core: prefix utilities with util_
author David Demelier <markand@malikania.fr>
date Sun, 06 Dec 2020 23:06:34 +0100
parents 60a214ec1ab4
children afdeafb82c22
files doc/docs/dev/api/core/util.md examples/CMakeLists.txt examples/example-battle/registry.c examples/example-font/main.c examples/example-label/main.c examples/example-map/CMakeLists.txt examples/example-map/main.c examples/example-message/main.c libmlk-adventure/adventure/actions/spawner.c libmlk-adventure/adventure/molko.c libmlk-adventure/adventure/state/mainmenu.c libmlk-adventure/adventure/state/map.c libmlk-adventure/adventure/state/panic.c libmlk-core/core/game.c libmlk-core/core/save.c libmlk-core/core/util.c libmlk-core/core/util.h libmlk-core/core/window.c libmlk-rpg/rpg/battle-bar.c libmlk-rpg/rpg/battle-state-selection.c libmlk-rpg/rpg/battle.c libmlk-rpg/rpg/map-file.c libmlk-rpg/rpg/tileset-file.c libmlk-ui/ui/theme.c
diffstat 24 files changed, 57 insertions(+), 464 deletions(-) [+]
line wrap: on
line diff
--- a/doc/docs/dev/api/core/util.md	Sun Dec 06 22:50:48 2020 +0100
+++ b/doc/docs/dev/api/core/util.md	Sun Dec 06 23:06:34 2020 +0100
@@ -10,26 +10,26 @@
 
 ## Macros
 
-### NELEM
+### UTIL_SIZE
 
 Get the number of elements in the static C array `x`.
 
 ```c
-#define NELEM(x) sizeof ((x)) / sizeof ((x)[0])
+#define UTIL_SIZE(x) sizeof ((x)) / sizeof ((x)[0])
 ```
 
 ## functions
 
-### delay
+### util_delay
 
 Put the thread to sleep for a given amount `ms` milliseconds.
 
 ```c
 void
-delay(unsigned int ms)
+util_delay(unsigned int ms)
 ```
 
-### pprintf
+### util_pathf
 
 Construct a temporary path to a file that can fit in a `PATH_MAX` array.
 
@@ -40,16 +40,16 @@
 
 ```c
 const char *
-pprintf(const char *fmt, ...)
+util_pathf(const char *fmt, ...)
 ```
 
-### nrand
+### util_nrand
 
 Returns a random number between `lower` and `upper` (included).
 
 ```c
 unsigned int
-nrand(unsigned int lower, unsigned int upper)
+util_nrand(unsigned int lower, unsigned int upper)
 ```
 
 [printf]: https://en.cppreference.com/w/c/io/fprintf
--- a/examples/CMakeLists.txt	Sun Dec 06 22:50:48 2020 +0100
+++ b/examples/CMakeLists.txt	Sun Dec 06 23:06:34 2020 +0100
@@ -26,25 +26,6 @@
 )
 
 set(
-	ASSETS_MAPS
-)
-
-set(
-	ASSETS_MAPS_SPRITES
-	${examples_SOURCE_DIR}/assets/maps/sprite-town.png
-	${examples_SOURCE_DIR}/assets/maps/sprite-world.png
-)
-
-set(
-	ASSETS_MAPS_ANIMATIONS
-	${examples_SOURCE_DIR}/assets/maps/animation-water.png
-)
-
-set(
-	ASSETS_TILESETS
-)
-
-set(
 	ASSETS_MUSIC
 	${examples_SOURCE_DIR}/assets/music/vabsounds-romance.ogg
 )
@@ -77,38 +58,13 @@
 # Can't use an interface library as examples live in subdirectories.
 file(WRITE ${examples_BINARY_DIR}/none.c "void molko() {}")
 
-# These files just need to be copied.
-file(MAKE_DIRECTORY ${cmake_BINARY_DIR}/assets/maps)
-
-foreach (s ${ASSETS_MAPS_SPRITES} ${ASSETS_MAPS_ANIMATIONS})
-	get_filename_component(basename ${s} NAME)
-	set(output ${examples_BINARY_DIR}/assets/maps/${basename})
-
-	add_custom_command(
-		OUTPUT ${output}
-		COMMENT "Copy ${basename}"
-		DEPENDS ${s}
-		COMMAND ${CMAKE_COMMAND} -E copy ${s} ${output}
-		VERBATIM
-	)
-
-	list(APPEND COPY_OUTPUTS ${output})
-endforeach ()
-
 molko_define_library(
 	TARGET libexamples
 	FOLDER examples
 	SOURCES
 		${examples_BINARY_DIR}/none.c
-		${COPY_OUTPUTS}
 		${ASSETS}
-		${ASSETS_MAPS}
-		${ASSETS_TILESETS}
-	PUBLIC_FLAGS
-		BINDIR="${examples_BINARY_DIR}"
 	ASSETS ${ASSETS}
-	MAPS ${ASSETS_MAPS}
-	TILESETS ${ASSETS_TILESETS}
 )
 
 add_subdirectory(example-action)
@@ -121,15 +77,12 @@
 add_subdirectory(example-font)
 add_subdirectory(example-gridmenu)
 add_subdirectory(example-label)
-add_subdirectory(example-map)
 add_subdirectory(example-message)
 add_subdirectory(example-sprite)
 add_subdirectory(example-trace)
 add_subdirectory(example-ui)
 
 source_group("assets/images" FILES ${ASSETS_IMAGES})
-source_group("assets/maps" FILES ${ASSETS_MAPS})
 source_group("assets/music" FILES ${ASSETS_MUSIC})
 source_group("assets/sounds" FILES ${ASSETS_SOUNDS})
 source_group("assets/sprites" FILES ${ASSETS_SPRITES})
-source_group("assets/tilesets" FILES ${ASSETS_TILESETS})
--- a/examples/example-battle/registry.c	Sun Dec 06 22:50:48 2020 +0100
+++ b/examples/example-battle/registry.c	Sun Dec 06 23:06:34 2020 +0100
@@ -83,7 +83,7 @@
 static void
 load_images(void)
 {
-	for (size_t i = 0; i < NELEM(images); ++i) {
+	for (size_t i = 0; i < UTIL_SIZE(images); ++i) {
 		struct texture *texture = &registry_images[images[i].index];
 
 		if (!image_openmem(texture, images[i].data, images[i].datasz))
@@ -94,7 +94,7 @@
 static void
 load_textures_and_sprites(void)
 {
-	for (size_t i = 0; i < NELEM(textures); ++i) {
+	for (size_t i = 0; i < UTIL_SIZE(textures); ++i) {
 		struct texture *texture = &registry_textures[textures[i].index];
 		struct sprite *sprite = &registry_sprites[textures[i].index];
 
@@ -111,7 +111,7 @@
 static void
 load_sounds(void)
 {
-	for (size_t i = 0; i < NELEM(sounds); ++i) {
+	for (size_t i = 0; i < UTIL_SIZE(sounds); ++i) {
 		struct sound *sound = &registry_sounds[sounds[i].index];
 
 		if (!sound_openmem(sound, sounds[i].data, sounds[i].datasz))
@@ -130,10 +130,10 @@
 void
 registry_finish(void)
 {
-	for (size_t i = 0; i < NELEM(registry_images); ++i)
+	for (size_t i = 0; i < UTIL_SIZE(registry_images); ++i)
 		texture_finish(&registry_images[i]);
-	for (size_t i = 0; i < NELEM(registry_textures); ++i)
+	for (size_t i = 0; i < UTIL_SIZE(registry_textures); ++i)
 		texture_finish(&registry_textures[i]);
-	for (size_t i = 0; i < NELEM(registry_sounds); ++i)
+	for (size_t i = 0; i < UTIL_SIZE(registry_sounds); ++i)
 		sound_finish(&registry_sounds[i]);
 }
--- a/examples/example-font/main.c	Sun Dec 06 22:50:48 2020 +0100
+++ b/examples/example-font/main.c	Sun Dec 06 23:06:34 2020 +0100
@@ -71,7 +71,7 @@
 				ci--;
 			break;
 		case KEY_RIGHT:
-			if ((size_t)ci < NELEM(colors))
+			if ((size_t)ci < UTIL_SIZE(colors))
 				ci++;
 			break;
 		case KEY_SPACE:
--- a/examples/example-label/main.c	Sun Dec 06 22:50:48 2020 +0100
+++ b/examples/example-label/main.c	Sun Dec 06 23:06:34 2020 +0100
@@ -16,6 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <stddef.h>
+
 #include <core/core.h>
 #include <core/event.h>
 #include <core/game.h>
@@ -107,7 +109,7 @@
 	if (!window_open("Example - Label", W, H))
 		panic();
 
-	for (size_t i = 0; i < NELEM(table); ++i) {
+	for (size_t i = 0; i < UTIL_SIZE(table); ++i) {
 		struct label *l = &table[i].label;
 		unsigned int w, h;
 
@@ -150,7 +152,7 @@
 	painter_set_color(0x4f8fbaff);
 	painter_clear();
 
-	for (size_t i = 0; i < NELEM(table); ++i)
+	for (size_t i = 0; i < UTIL_SIZE(table); ++i)
 		label_draw(&table[i].label);
 
 	label_draw(&mlabel);
--- a/examples/example-map/CMakeLists.txt	Sun Dec 06 22:50:48 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-#
-# CMakeLists.txt -- CMake build system for molko
-#
-# Copyright (c) 2020 David Demelier <markand@malikania.fr>
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-
-project(example-map)
-
-molko_define_executable(
-	TARGET example-map
-	SOURCES ${example-map_SOURCE_DIR}/main.c
-	FOLDER examples
-	LIBRARIES libmlk-rpg libexamples
-)
--- a/examples/example-map/main.c	Sun Dec 06 22:50:48 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,307 +0,0 @@
-/*
- * example-map.c -- show how to use maps
- *
- * Copyright (c) 2020 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <core/alloc.h>
-#include <core/core.h>
-#include <core/event.h>
-#include <core/game.h>
-#include <core/image.h>
-#include <core/maths.h>
-#include <core/painter.h>
-#include <core/panic.h>
-#include <core/state.h>
-#include <core/texture.h>
-#include <core/window.h>
-
-#include <ui/ui.h>
-
-#include <rpg/map.h>
-#include <rpg/map-file.h>
-#include <rpg/rpg.h>
-#include <rpg/teleport.h>
-
-#include <assets/sprites/john.h>
-
-#define W       (1280)
-#define H       (720)
-
-static void load_action(struct map *, int, int, int, int, const char *);
-
-struct map_state {
-	struct map_file loader;
-	struct map map;
-	struct state state;
-};
-
-static struct texture john_texture;
-static struct sprite john_sprite;
-
-static void
-map_state_start(struct state *st)
-{
-	struct map_state *ms = st->data;
-
-	game.inhibit &= ~(INHIBIT_STATE_INPUT);
-
-	if (!map_init(&ms->map))
-		panic();
-}
-
-static void
-map_state_update(struct state *st, unsigned int ticks)
-{
-	struct map_state *ms = st->data;
-
-	map_update(&ms->map, ticks);
-}
-
-static void
-map_state_handle(struct state *st, const union event *ev)
-{
-	struct map_state *ms = st->data;
-
-	switch (ev->type) {
-	case EVENT_QUIT:
-		game_quit();
-		break;
-	default:
-		map_handle(&ms->map, ev);
-		break;
-	}
-}
-
-static void
-map_state_draw(struct state *st)
-{
-	struct map_state *ms = st->data;
-
-	painter_set_color(0xffffffff);
-	painter_clear();
-	map_draw(&ms->map);
-	painter_present();
-}
-
-static void
-map_state_finish(struct state *state)
-{
-	struct map_state *ms = state->data;
-
-	map_finish(&ms->map);
-	map_file_finish(&ms->loader);
-}
-
-static struct state *
-map_state_new(const char *name, int ox, int oy)
-{
-	char path[1024];
-	struct map_state *ms;
-
-	ms = alloc_new0(sizeof (*ms));
-	ms->loader.load_action = load_action;
-
-	snprintf(path, sizeof (path), "%s/assets/maps/%s.map", BINDIR, name);
-
-	if (!map_file_open(&ms->loader, &ms->map, path))
-		panic();
-
-	/* TODO: we may need to add a function in loader. */
-	ms->map.player_sprite = &john_sprite;
-
-	/* Override origin. */
-	if (ox >= 0 && oy >= 0) {
-		ms->map.player_x = ox;
-		ms->map.player_y = oy;
-	}
-
-	map_init(&ms->map);
-	ms->state.data = ms;
-	ms->state.start = map_state_start;
-	ms->state.handle = map_state_handle;
-	ms->state.update = map_state_update;
-	ms->state.draw = map_state_draw;
-	ms->state.finish = map_state_finish;
-
-	return &ms->state;
-}
-
-struct teleport_effect {
-	struct action act;
-	struct teleport tp;
-};
-
-static void
-teleport_effect_draw(struct action *act)
-{
-	struct teleport_effect *fx = act->data;
-
-	teleport_draw(&fx->tp);
-}
-
-static bool
-teleport_effect_update(struct action *act, unsigned int ticks)
-{
-	struct teleport_effect *fx = act->data;
-
-	return teleport_update(&fx->tp, ticks);
-}
-
-static void
-teleport_effect_finish(struct action *act)
-{
-	struct teleport_effect *fx = act->data;
-
-	teleport_finish(&fx->tp);
-}
-
-static void
-teleport_effect(struct map *current_map, const char *name, int ox, int oy)
-{
-	struct teleport_effect *fx;
-
-	fx = alloc_new0(sizeof (*fx));
-	fx->tp.state = map_state_new(name, ox, oy);
-
-	fx->act.data = fx;
-	fx->act.draw = teleport_effect_draw;
-	fx->act.update = teleport_effect_update;
-	fx->act.finish = teleport_effect_finish;
-
-	/* Stop movement. */
-	current_map->player_movement = 0;
-
-	/* Player isn't allowed to move anymore. */
-	game.inhibit = INHIBIT_STATE_INPUT;
-
-	teleport_start(&fx->tp);
-	action_stack_add(&current_map->astack_par, &fx->act);
-}
-
-struct teleport_touch {
-	struct action act;
-	struct map *map;        /* Current map. */
-	int ox;                 /* Override origin x. (-1 to use map's default). */
-	int oy;                 /* Same in y. */
-	char name[256];
-	int x;
-	int y;
-	unsigned int w;
-	unsigned int h;
-};
-
-static bool
-teleport_touch_update(struct action *act, unsigned int ticks)
-{
-	(void)ticks;
-
-	const struct teleport_touch *touch = act->data;
-
-	const int x = touch->x - touch->map->player_sprite->cellw;
-	const int y = touch->y - touch->map->player_sprite->cellh;
-	const unsigned int w = touch->w + touch->map->player_sprite->cellw;
-	const unsigned int h = touch->h + touch->map->player_sprite->cellh;
-
-	if (maths_is_boxed(x, y, w, h, touch->map->player_x, touch->map->player_y)) {
-		teleport_effect(touch->map, touch->name, touch->ox, touch->oy);
-		return true;
-	}
-
-	return false;
-}
-
-static void
-teleport_touch_finish(struct action *act)
-{
-	free(act->data);
-}
-
-static struct action *
-teleport_touch_new(struct map *map, int x, int y, int w, int h, const char *def)
-{
-	char name[256];
-	int ox = -1, oy = -1;
-	struct teleport_touch *touch;
-
-	if (sscanf(def, "%255[^:]:%d:%d", name, &ox, &oy) < 1)
-		panicf("could not parse teleport destination");
-
-	touch = alloc_new0(sizeof (*touch));
-	touch->map = map;
-	touch->ox = ox;
-	touch->oy = oy;
-	touch->x = x;
-	touch->y = y;
-	touch->w = w;
-	touch->h = h;
-	snprintf(touch->name, sizeof (touch->name), "%s", name);
-
-	touch->act.data = touch;
-	touch->act.update = teleport_touch_update;
-	touch->act.finish = teleport_touch_finish;
-
-	return &touch->act;
-}
-
-static void
-load_action(struct map *map, int x, int y, int w, int h, const char *id)
-{
-	if (strncmp(id, "teleport:", 9) == 0)
-		action_stack_add(&map->astack_par, teleport_touch_new(map, x, y, w, h, id + 9));
-}
-
-static void
-init(void)
-{
-	if (!core_init("fr.malikania", "map") || !ui_init())
-		panic();
-	if (!window_open("Example - Map", W, H))
-		panic();
-	if (!image_openmem(&john_texture, sprites_john, sizeof (sprites_john)))
-		panic();
-
-	sprite_init(&john_sprite, &john_texture, 48, 48);
-}
-
-static void
-quit(void)
-{
-	window_finish();
-	ui_finish();
-	core_finish();
-}
-
-static void
-run(void)
-{
-	game_switch(map_state_new("map-world", -1, -1), true);
-	game_loop();
-}
-
-int
-main(int argc, char **argv)
-{
-	(void)argc;
-	(void)argv;
-
-	init();
-	run();
-	quit();
-}
--- a/examples/example-message/main.c	Sun Dec 06 22:50:48 2020 +0100
+++ b/examples/example-message/main.c	Sun Dec 06 23:06:34 2020 +0100
@@ -16,6 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <stddef.h>
+
 #include <core/core.h>
 #include <core/event.h>
 #include <core/game.h>
--- a/libmlk-adventure/adventure/actions/spawner.c	Sun Dec 06 22:50:48 2020 +0100
+++ b/libmlk-adventure/adventure/actions/spawner.c	Sun Dec 06 23:06:34 2020 +0100
@@ -85,7 +85,7 @@
 	self->map = map;
 	self->last_x = map->player_x;
 	self->last_y = map->player_y;
-	self->steps = nrand(low, high);
+	self->steps = util_nrand(low, high);
 
 	self->action.data = self;
 	self->action.update = update;
--- a/libmlk-adventure/adventure/molko.c	Sun Dec 06 22:50:48 2020 +0100
+++ b/libmlk-adventure/adventure/molko.c	Sun Dec 06 23:06:34 2020 +0100
@@ -56,34 +56,6 @@
 	longjmp(panic_buf, 1);
 }
 
-static void
-loop(void)
-{
-	struct clock clock = {0};
-
-	while (game.state) {
-		unsigned int elapsed = clock_elapsed(&clock);
-
-		clock_start(&clock);
-
-		for (union event ev; event_poll(&ev); ) {
-			switch (ev.type) {
-			case EVENT_QUIT:
-				return;
-			default:
-				game_handle(&ev);
-				break;
-			}
-		}
-
-		game_update(elapsed);
-		game_draw();
-
-		if ((elapsed = clock_elapsed(&clock)) < 20)
-			delay(20 - elapsed);
-	}
-}
-
 void
 molko_init(void)
 {
@@ -115,14 +87,14 @@
 {
 	if (setjmp(panic_buf) == 0) {
 		/* Initial game run. */
-		loop();
+		game_loop();
 	} else {
 		/* Clear event queue to avoid accidental key presses. */
 		for (union event ev; event_poll(&ev); )
 			continue;
 
 		game_switch(molko.panic, true);
-		loop();
+		game_loop();
 	}
 }
 
@@ -139,7 +111,7 @@
 	assert(file);
 
 	/* TODO: libmlk-adventure must be renamed. */
-	return pprintf("%s/libmlk-adventure/%s", sys_dir(SYS_DIR_DATA), file);
+	return util_pathf("%s/libmlk-adventure/%s", sys_dir(SYS_DIR_DATA), file);
 }
 
 void
--- a/libmlk-adventure/adventure/state/mainmenu.c	Sun Dec 06 22:50:48 2020 +0100
+++ b/libmlk-adventure/adventure/state/mainmenu.c	Sun Dec 06 23:06:34 2020 +0100
@@ -171,7 +171,7 @@
 	painter_set_color(0xffffffff);
 	painter_clear();
 
-	for (size_t i = 0; i < NELEM(self->texts); ++i)
+	for (size_t i = 0; i < UTIL_SIZE(self->texts); ++i)
 		texture_draw(&self->texts[i].tex, self->texts[i].x, self->texts[i].y);
 
 	/* TODO: a sword here. */
@@ -187,7 +187,7 @@
 {
 	struct self *self = state->data;
 
-	for (size_t i = 0; i < NELEM(self->texts); ++i)
+	for (size_t i = 0; i < UTIL_SIZE(self->texts); ++i)
 		texture_finish(&self->texts[i].tex);
 
 	free(self);
--- a/libmlk-adventure/adventure/state/map.c	Sun Dec 06 22:50:48 2020 +0100
+++ b/libmlk-adventure/adventure/state/map.c	Sun Dec 06 23:06:34 2020 +0100
@@ -79,7 +79,7 @@
 		{ "spawner|",   load_spawner }
 	};
 
-	for (size_t i = 0; i < NELEM(table); ++i) {
+	for (size_t i = 0; i < UTIL_SIZE(table); ++i) {
 		size_t len = strlen(table[i].name);
 
 		if (strncmp(table[i].name, value, len) == 0) {
--- a/libmlk-adventure/adventure/state/panic.c	Sun Dec 06 22:50:48 2020 +0100
+++ b/libmlk-adventure/adventure/state/panic.c	Sun Dec 06 23:06:34 2020 +0100
@@ -125,7 +125,7 @@
 		die("%s", error());
 
 	/* All align x the same. */
-	for (size_t i = 0; i < NELEM(self->texts); ++i)
+	for (size_t i = 0; i < UTIL_SIZE(self->texts); ++i)
 		self->texts[i].x = theme->padding;
 
 	/* Header (0-1). */
@@ -165,7 +165,7 @@
 	painter_set_color(BACKGROUND);
 	painter_clear();
 
-	for (size_t i = 0; i < NELEM(self->texts); ++i)
+	for (size_t i = 0; i < UTIL_SIZE(self->texts); ++i)
 		texture_draw(&self->texts[i].tex, self->texts[i].x, self->texts[i].y);
 
 	/* The error is only available here. */
@@ -187,7 +187,7 @@
 {
 	struct self *self = state->data;
 
-	for (size_t i = 0; i < NELEM(self->texts); ++i)
+	for (size_t i = 0; i < UTIL_SIZE(self->texts); ++i)
 		texture_finish(&self->texts[i].tex);
 
 	free(self);
--- a/libmlk-core/core/game.c	Sun Dec 06 22:50:48 2020 +0100
+++ b/libmlk-core/core/game.c	Sun Dec 06 23:06:34 2020 +0100
@@ -141,7 +141,7 @@
 		 * a little to save CPU cycles.
 		 */
 		if ((elapsed = clock_elapsed(&clock)) < frametime)
-			delay(frametime - elapsed);
+			util_delay(frametime - elapsed);
 
 		elapsed = clock_elapsed(&clock);
 	}
--- a/libmlk-core/core/save.c	Sun Dec 06 22:50:48 2020 +0100
+++ b/libmlk-core/core/save.c	Sun Dec 06 23:06:34 2020 +0100
@@ -52,7 +52,7 @@
 static const char *
 path(unsigned int idx)
 {
-	return pprintf("%s/%u", sys_dir(SYS_DIR_SAVE), idx);
+	return util_pathf("%s/%u", sys_dir(SYS_DIR_SAVE), idx);
 }
 
 static bool
@@ -81,7 +81,7 @@
 	};
 
 	/* Ensure create and update dates are present. */
-	for (size_t i = 0; i < NELEM(table); ++i) {
+	for (size_t i = 0; i < UTIL_SIZE(table); ++i) {
 		if (!save_get_property(db, &table[i].prop)) {
 			sqlite3_close(db->handle);
 			return errorf(_("database not initialized correctly"));
--- a/libmlk-core/core/util.c	Sun Dec 06 22:50:48 2020 +0100
+++ b/libmlk-core/core/util.c	Sun Dec 06 23:06:34 2020 +0100
@@ -25,13 +25,13 @@
 #include "util.h"
 
 void
-delay(unsigned int ms)
+util_delay(unsigned int ms)
 {
 	SDL_Delay(ms);
 }
 
 const char *
-pprintf(const char *fmt, ...)
+util_pathf(const char *fmt, ...)
 {
 	static char path[PATH_MAX];
 	va_list ap;
@@ -44,7 +44,7 @@
 }
 
 unsigned int
-nrand(unsigned int lower, unsigned int upper)
+util_nrand(unsigned int lower, unsigned int upper)
 {
 	assert(upper <= RAND_MAX);
 
--- a/libmlk-core/core/util.h	Sun Dec 06 22:50:48 2020 +0100
+++ b/libmlk-core/core/util.h	Sun Dec 06 23:06:34 2020 +0100
@@ -19,18 +19,15 @@
 #ifndef MOLKO_CORE_UTIL_H
 #define MOLKO_CORE_UTIL_H
 
-#include <stdarg.h>
-#include <stddef.h>
-
-#define NELEM(x) sizeof ((x)) / sizeof ((x)[0])
+#define UTIL_SIZE(x) sizeof ((x)) / sizeof ((x)[0])
 
 void
-delay(unsigned int ms);
+util_delay(unsigned int ms);
 
 const char *
-pprintf(const char *fmt, ...);
+util_pathf(const char *fmt, ...);
 
 unsigned int
-nrand(unsigned int lower, unsigned int upper);
+util_nrand(unsigned int lower, unsigned int upper);
 
 #endif /* !MOLKO_CORE_UTIL_H */
--- a/libmlk-core/core/window.c	Sun Dec 06 22:50:48 2020 +0100
+++ b/libmlk-core/core/window.c	Sun Dec 06 23:06:34 2020 +0100
@@ -61,7 +61,7 @@
 static void
 finish_cursors(void)
 {
-	for (size_t i = 0; i < NELEM(cursors); ++i)
+	for (size_t i = 0; i < UTIL_SIZE(cursors); ++i)
 		if (cursors[i])
 			SDL_FreeCursor(cursors[i]);
 }
--- a/libmlk-rpg/rpg/battle-bar.c	Sun Dec 06 22:50:48 2020 +0100
+++ b/libmlk-rpg/rpg/battle-bar.c	Sun Dec 06 23:06:34 2020 +0100
@@ -167,7 +167,7 @@
 	/* Draw menu frame. */
 	frame_draw(&bar->menu_frame);
 
-	for (size_t i = 0; i < NELEM(buttons); ++i) {
+	for (size_t i = 0; i < UTIL_SIZE(buttons); ++i) {
 		buttons[i].label.theme = &theme;
 
 		label_query(&buttons[i].label, &buttons[i].w, &buttons[i].h);
--- a/libmlk-rpg/rpg/battle-state-selection.c	Sun Dec 06 22:50:48 2020 +0100
+++ b/libmlk-rpg/rpg/battle-state-selection.c	Sun Dec 06 23:06:34 2020 +0100
@@ -69,11 +69,11 @@
 	switch (select->type) {
 	case SELECTION_TEAM_ONE:
 	case SELECTION_TEAM_COMBINED:
-		select_adj_in(select, bt->team, NELEM(bt->team), step);
+		select_adj_in(select, bt->team, UTIL_SIZE(bt->team), step);
 		break;
 	case SELECTION_ENEMY_ONE:
 	case SELECTION_ENEMY_COMBINED:
-		select_adj_in(select, bt->enemies, NELEM(bt->enemies), step);
+		select_adj_in(select, bt->enemies, UTIL_SIZE(bt->enemies), step);
 	default:
 		break;
 	}
@@ -181,12 +181,12 @@
 	case SELECTION_ENEMY_ALL:
 	case SELECTION_ENEMY_ONE:
 	case SELECTION_ENEMY_COMBINED:
-		draw_cursors(st, bt, bt->enemies, NELEM(bt->enemies));
+		draw_cursors(st, bt, bt->enemies, UTIL_SIZE(bt->enemies));
 		break;
 	case SELECTION_TEAM_ALL:
 	case SELECTION_TEAM_ONE:
 	case SELECTION_TEAM_COMBINED:
-		draw_cursors(st, bt, bt->team, NELEM(bt->team));
+		draw_cursors(st, bt, bt->team, UTIL_SIZE(bt->team));
 		break;
 	default:
 		break;
--- a/libmlk-rpg/rpg/battle.c	Sun Dec 06 22:50:48 2020 +0100
+++ b/libmlk-rpg/rpg/battle.c	Sun Dec 06 23:06:34 2020 +0100
@@ -368,8 +368,8 @@
 	action_stack_update(&bt->actions[1], ticks);
 	drawable_stack_update(&bt->effects, ticks);
 
-	update_entities(bt->team, NELEM(bt->team), ticks);
-	update_entities(bt->enemies, NELEM(bt->enemies), ticks);
+	update_entities(bt->team, UTIL_SIZE(bt->team), ticks);
+	update_entities(bt->enemies, UTIL_SIZE(bt->enemies), ticks);
 
 	/* Game cannot update if the actions[0] stack isn't completed. */
 	if (!action_stack_completed(&bt->actions[0]))
@@ -393,8 +393,8 @@
 		    0.f);
 
 	/* Draw entities. */
-	draw_entities(bt, bt->team, NELEM(bt->team));
-	draw_entities(bt, bt->enemies, NELEM(bt->enemies));
+	draw_entities(bt, bt->team, UTIL_SIZE(bt->team));
+	draw_entities(bt, bt->enemies, UTIL_SIZE(bt->enemies));
 
 	battle_bar_draw(&bt->bar, bt);
 
--- a/libmlk-rpg/rpg/map-file.c	Sun Dec 06 22:50:48 2020 +0100
+++ b/libmlk-rpg/rpg/map-file.c	Sun Dec 06 23:06:34 2020 +0100
@@ -210,7 +210,7 @@
 		{ "layer",      parse_layer             },
 	};
 
-	for (size_t i = 0; i < NELEM(props); ++i)
+	for (size_t i = 0; i < UTIL_SIZE(props); ++i)
 		if (strncmp(line, props[i].property, strlen(props[i].property)) == 0)
 			return props[i].read(ctx, line);
 
--- a/libmlk-rpg/rpg/tileset-file.c	Sun Dec 06 22:50:48 2020 +0100
+++ b/libmlk-rpg/rpg/tileset-file.c	Sun Dec 06 23:06:34 2020 +0100
@@ -196,7 +196,7 @@
 
 		if (!(anim = alloc_pool_new(&ctx->tf->anims[0])))
 			return false;
-		if (!image_open(&anim->texture, pprintf("%s/%s", ctx->basedir, filename)))
+		if (!image_open(&anim->texture, util_pathf("%s/%s", ctx->basedir, filename)))
 			return false;
 
 		sprite_init(&anim->sprite, &anim->texture, ctx->tilewidth, ctx->tileheight);
@@ -239,7 +239,7 @@
 	if (!(p = strchr(line, '|')))
 		return errorf(_("could not parse image"));
 
-	if (!image_open(&ctx->tf->image, pprintf("%s/%s", ctx->basedir, p + 1)))
+	if (!image_open(&ctx->tf->image, util_pathf("%s/%s", ctx->basedir, p + 1)))
 		return false;
 
 	sprite_init(&ctx->tf->sprite, &ctx->tf->image, ctx->tilewidth, ctx->tileheight);
@@ -262,7 +262,7 @@
 		{ "image",      parse_image             }
 	};
 
-	for (size_t i = 0; i < NELEM(props); ++i) {
+	for (size_t i = 0; i < UTIL_SIZE(props); ++i) {
 		if (strncmp(line, props[i].property, strlen(props[i].property)) == 0)
 			return props[i].read(ctx, line);
 	}
--- a/libmlk-ui/ui/theme.c	Sun Dec 06 22:50:48 2020 +0100
+++ b/libmlk-ui/ui/theme.c	Sun Dec 06 23:06:34 2020 +0100
@@ -73,7 +73,7 @@
 theme_init(void)
 {
 	/* Open all fonts. */
-	for (size_t i = 0; i < NELEM(default_fonts); ++i) {
+	for (size_t i = 0; i < UTIL_SIZE(default_fonts); ++i) {
 		struct font_catalog *fc = &default_fonts[i];
 
 		if (!font_openmem(&fc->font, fc->data, fc->datasz, fc->size))
@@ -146,7 +146,7 @@
 void
 theme_finish(void)
 {
-	for (size_t i = 0; i < NELEM(default_fonts); ++i) {
+	for (size_t i = 0; i < UTIL_SIZE(default_fonts); ++i) {
 		font_finish(&default_fonts[i].font);
 		*default_fonts[i].dest = NULL;
 	}