--- /dev/null
+[submodule "src/cutils"]
+ path = src/cutils
+ url = git@git.nikiroo.be:workspace/cutils.git
+ branch = subtree
# > NAMES: list of all the programs to compile
# > TESTS: list of all test programs to compile and run
#
-NAME = program
-NAMES = $(NAME) program2
-TESTS = tests-program
+NAME = tdef
+NAMES = $(NAME)
+TESTS =
################################################################################
--- /dev/null
+Subproject commit d6fa07c12023662e16ace68bba78047e0244a9f7
--- /dev/null
+# Simply pass everything to makefile.d, but calling from "../"
+
+.PHONY: default $(MAKECMDGOALS)
+
+default $(MAKECMDGOALS):
+ @for mk in makefile.d; do \
+ $(MAKE) --no-print-directory -C ../ -f "$(CURDIR)/$$mk" \
+ $(MAKECMDGOALS); \
+ done;
+
--- /dev/null
+/*
+ * TDef: small tower defense game
+ *
+ * Copyright (C) 2025 Niki Roo
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "any.h"
+
+path_t *anyloc(any_t *self) {
+ if (self && self->_.type == 'l')
+ return (path_t*)(void*)self;
+ return NULL;
+}
+
+tower_t *anytower(any_t *self) {
+ if (self && self->_.type == 't')
+ return (tower_t*)(void*)self;
+ return NULL;
+}
+
+enemy_t *anyenemy(any_t *self) {
+ if (self && self->_.type == 'e')
+ return (enemy_t*)(void*)self;
+ return NULL;
+}
+
+any_t *loc2any(path_t *self) {
+ return (any_t*)(void*)self;
+}
+
+any_t *tower2any(tower_t *self) {
+ return (any_t*)(void*)self;
+}
+
+any_t *enemy2any(enemy_t *self) {
+ return (any_t*)(void*)self;
+}
+
--- /dev/null
+/**
+ * @file any.h
+ * @author Niki
+ * @date 2025
+ *
+ * @brief bla
+ *
+ * blablabla
+ *
+ */
+
+#ifndef ANY_H
+#define ANY_H
+
+#include "path.h"
+#include "tower.h"
+#include "enemy.h"
+
+/**
+ * @brief bla
+ *
+ * blablabla
+ */
+typedef union {
+ struct { char _; char type; } _;
+ path_t _l;
+ tower_t _t;
+ enemy_t _e;
+} any_t;
+
+path_t *anyloc(any_t *self);
+
+tower_t *anytower(any_t *self);
+
+enemy_t *anyenemy(any_t *self);
+
+any_t *loc2any(path_t *self);
+
+any_t *tower2any(tower_t *self);
+
+any_t *enemy2any(enemy_t *self);
+
+#endif /* ANY_H */
+
--- /dev/null
+/*
+ * TDef: small tower defense game
+ *
+ * Copyright (C) 2025 Niki Roo
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "enemy.h"
+
+enemy_t *new_enemy(size_t start_tick) {
+ enemy_t *self = malloc(sizeof(enemy_t));
+ if (!init_enemy(self, start_tick)) {
+ free(self);
+ self = NULL;
+ }
+
+ return self;
+}
+
+int init_enemy(enemy_t *self, size_t start_tick) {
+ size_t sz = sizeof(self->CNAME);
+ strncpy(self->CNAME, "[enemy ", sz);
+ self->CNAME[sz - 2] = ']';
+ self->CNAME[sz - 1] = '\0';
+
+ self->start_tick = start_tick;
+
+ return 1;
+}
+
+void free_enemy(enemy_t *self) {
+ if (self)
+ uninit_enemy(self);
+
+ free(self);
+}
+
+void uninit_enemy(enemy_t *self) {
+ self->CNAME[0] = '!';
+}
+
--- /dev/null
+/**
+ * @file enemy.h
+ * @author Niki
+ * @date 2025
+ *
+ * @brief bla
+ *
+ * blablabla
+ *
+ */
+
+#ifndef ENEMY_H
+#define ENEMY_H
+
+#include <stddef.h>
+
+/**
+ * @brief bla
+ *
+ * blablabla
+ */
+typedef struct {
+ char CNAME[10];
+ size_t start_tick;
+ int hp;
+ int speed; // paths per tick
+} enemy_t;
+
+/**
+ * Create a new enemy.
+ *
+ * @param start_tick the tick at which the enemy will start on the map
+ *
+ * @note always identical to <tt>malloc</tt> + <tt>init_enemy</tt>
+ *
+ * @see malloc()
+ * @see init_enemy(enemy_t *self)
+ *
+ * @return a new enemy (you must later call `free_enemy()`)
+ */
+enemy_t *new_enemy(size_t start_tick);
+
+/**
+ * Initialise a new enemy.
+ *
+ * @param start_tick the tick at which the enemy will start on the map
+ */
+int init_enemy(enemy_t *self, size_t start_tick);
+
+/**
+ * Free the resources held for the given enemy: you must not use it any more.
+ *
+ * @note always equivalent to <tt>uninit_enemy</tt> + <tt>free</tt>
+ *
+ * @see uninit_enemy(enemy_t *self)
+ * @see free(void *data)
+ */
+void free_enemy(enemy_t *self);
+
+/**
+ * Free the resources held for the given enemy: you must not use it any more
+ * unless you call <tt>init_enemy</tt> on it again.
+ *
+ * The memory pointed to by <tt>self</tt> is <i>not</i> free'd.
+ *
+ *
+ * @see init_enemy(enemy_t *self)
+ */
+void uninit_enemy(enemy_t *self);
+
+#endif /* ENEMY_H */
--- /dev/null
+/*
+ * TDef: small tower defense game
+ *
+ * Copyright (C) 2025 Niki Roo
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "engine.h"
+
+void move(engine_t *self, enemy_t *enemy, path_t *path);
+
+engine_t *new_engine(map_t *map) {
+ engine_t *self = malloc(sizeof(engine_t));
+ if (!init_engine(self, map)) {
+ free(self);
+ self = NULL;
+ }
+
+ return self;
+}
+
+int init_engine(engine_t *self, map_t *map) {
+ size_t sz = sizeof(self->CNAME);
+ strncpy(self->CNAME, "[engine ", sz);
+ self->CNAME[sz - 2] = ']';
+ self->CNAME[sz - 1] = '\0';
+
+ self->map = map;
+ self->current_tick = 0;
+ self->events = new_array(sizeof(int), 10);
+ self->last_enemy = NULL;
+
+ return (self->events != NULL);
+}
+
+void free_engine(engine_t *self) {
+ if (self)
+ uninit_engine(self);
+
+ free(self);
+}
+
+void uninit_engine(engine_t *self) {
+ self->CNAME[0] = '!';
+ free_map(self->map);
+ self->map = NULL;
+ free_array(self->events);
+ self->events = NULL;
+}
+
+void engine_tick(engine_t *self) {
+printf("Tick is: %d\n", self->current_tick);
+ array_clear(self->events);
+
+ // TODO: all the rest
+
+ enemy_t *enemy;
+ if (self->last_enemy)
+ enemy = array_next(self->map->enemies, self->last_enemy);
+ else
+ enemy = array_first(self->map->enemies);
+
+ // We allow only one enemy per tick (because one per path!)
+ if (enemy->start_tick == self->current_tick) {
+ move(self, enemy, array_first(self->map->paths));
+ }
+
+ self->current_tick++;
+}
+
+
+void move(engine_t *self, enemy_t *enemy, path_t *path) {
+ if (path->enemy)
+ printf("woops: TODO");
+
+ path->enemy = enemy;
+}
+
--- /dev/null
+/**
+ * @file engine.h
+ * @author Niki
+ * @date 2025
+ *
+ * @brief bla
+ *
+ * blablabla
+ *
+ */
+
+#ifndef ENGINE_H
+#define ENGINE_H
+
+#include <stddef.h>
+#include "cutils/array.h"
+#include "map.h"
+
+/**
+ * @brief bla
+ *
+ * blablabla
+ */
+typedef struct {
+ char CNAME[10];
+ map_t *map;
+ size_t current_tick;
+ array_t *events;
+ enemy_t *last_enemy;
+} engine_t;
+
+/**
+ * Create a new engine.
+ *
+ * @param map the game map (will be owned by this engine)
+ *
+ * @note always identical to <tt>malloc</tt> + <tt>init_engine</tt>
+ *
+ * @see malloc()
+ * @see init_engine(engine_t *self)
+ *
+ * @return a new engine (you must later call `free_engine()`)
+ */
+engine_t *new_engine(map_t *map);
+
+/**
+ * Initialise a new engine.
+ *
+ * @param map the game map (will be owned by this engine)
+ */
+int init_engine(engine_t *self, map_t *map);
+
+/**
+ * Free the resources held for the given engine: you must not use it any more.
+ * The map will also be free'd.
+ *
+ * @note always equivalent to <tt>uninit_engine</tt> + <tt>free</tt>
+ *
+ * @see uninit_engine(engine_t *self)
+ * @see free(void *data)
+ */
+void free_engine(engine_t *self);
+
+/**
+ * Free the resources held for the given engine: you must not use it any more
+ * unless you call <tt>init_engine</tt> on it again.
+ * The map will also be free'd.
+ *
+ * The memory pointed to by <tt>self</tt> is <i>not</i> free'd.
+ *
+ *
+ * @see init_engine(engine_t *self)
+ */
+void uninit_engine(engine_t *self);
+
+// will clear events on start!
+void engine_tick(engine_t *self);
+
+#endif /* ENGINE_H */
+
--- /dev/null
+#
+# Makefile for C projets
+# > NAME : the name of the main program (if programs, make a single .d file
+# per program, link them up in Makfile and use a $ssrcdir)
+# > srcdir : the source directory
+# > ssrcdir: the sub-sources directory (defaults to $srcdir)
+# > dstdir: the destination directory (defaults to $srcdir/bin)
+#
+# Environment variables:
+# > PREFIX: where to (un)install (defaults to /usr/local)
+# > DEBUG: define it to build with all debug symbols
+#
+NAME = tdef
+srcdir = $(NAME)
+ssrcdir = $(srcdir)
+
+# Note: c99+ required for for-loop initial declaration (not default in CentOS 6)
+# Note: gnu99 can be required for some projects (i.e.: libcutils-net)
+CFLAGS += -Wall -pedantic -I./ -std=c99
+CXXFLAGS += -Wall -pedantic -I./
+PREFIX = /usr/local
+
+# Required libraries if any:
+# LDFLAGS += -lcheck $(shell pkg-config --libs --clfags check)
+
+# Required *locally compiled* libraries if any:
+# LIBS = cutils
+LIBS = cutils
+
+################################################################################
+
+ifeq ($(dstdir),)
+dstdir = $(srcdir)/bin
+endif
+
+ifdef DEBUG
+CFLAGS += -ggdb -O0
+CXXFLAGS += -ggdb -O0
+endif
+
+# Default target
+.PHONY: all deps
+all:
+
+# locally compiled libs:
+ifneq ($(LIBS),)
+LDFLAGS += -L$(dstdir)
+LDFLAGS += $(foreach lib,$(LIBS),-l$(lib))
+endif
+deps:
+ $(foreach lib,$(LIBS),$(MAKE) --no-print-directory \
+ -C $(lib)/ $(lib) dstdir=$(dstdir))
+
+.PHONY: build rebuild install uninstall clean mrpropre mrpropre \
+ $(NAME) test run run-test run-test-more
+
+SOURCES=$(wildcard $(ssrcdir)/*.c)
+OBJECTS=$(SOURCES:%.c=%.o)
+DEPENDS =$(SOURCES:%.c=%.d)
+
+# Autogenerate dependencies from code
+-include $(DEPENDS)
+%.o: %.c
+ $(CC) $(CFLAGS) -MMD -MP -c $< -o $@
+
+# Main targets
+
+all: build
+
+build: $(NAME)
+
+rebuild: clean build
+
+$(NAME): deps $(dstdir)/$(NAME)
+
+# Program, so no test
+run:
+ @echo
+ $(dstdir)/$(NAME) --help
+test run-test run-test-more:
+ @echo you are in the sources of the program, look at the tests instead
+
+$(dstdir)/$(NAME): $(OBJECTS)
+ mkdir -p $(dstdir)
+ # note: LDFLAGS *must* be near the end
+ $(CC) $(CFLAGS) $(OBJECTS) -o $@ $(LDFLAGS)
+
+clean:
+ $(foreach lib,$(LIBS),$(MAKE) --no-print-directory \
+ -C $(lib)/ $@ dstdir=$(dstdir))
+ rm -f $(OBJECTS)
+ rm -f $(DEPENDS)
+
+mrproper: mrpropre
+mrpropre: clean
+ $(foreach lib,$(LIBS),$(MAKE) --no-print-directory \
+ -C $(lib)/ $@ dstdir=$(dstdir))
+ rm -f $(dstdir)/$(NAME)
+ rmdir $(dstdir) 2>/dev/null || true
+
+install: build
+ mkdir -p "$(PREFIX)/bin"
+ cp "$(dstdir)/$(NAME)" "$(PREFIX)/bin/"
+
+uninstall:
+ rm "$(PREFIX)/bin/$(NAME)"
+ rmdir "$(PREFIX)/bin" 2>/dev/null
+
--- /dev/null
+/*
+ * TDef: small tower defense game
+ *
+ * Copyright (C) 2025 Niki Roo
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "map.h"
+
+map_t *new_map(int width, int height) {
+ map_t *self = malloc(sizeof(map_t));
+ if (!init_map(self, width, height)) {
+ free(self);
+ self = NULL;
+ }
+
+ return self;
+}
+
+int init_map(map_t *self, int width, int height) {
+ size_t sz = sizeof(self->CNAME);
+ strncpy(self->CNAME, "[map ", sz);
+ self->CNAME[sz - 2] = ']';
+ self->CNAME[sz - 1] = '\0';
+
+ self->width = width;
+ self->height = height;
+ self->data = calloc((width*height), sizeof(any_t*));
+
+ self->paths = new_array(sizeof(path_t ), 100);
+ self->towers = new_array(sizeof(tower_t*), 20);
+ self->enemies = new_array(sizeof(enemy_t ), 100);
+ self->alive = new_array(sizeof(enemy_t*), 10);
+
+ if (!self->data || !self->paths || !self->towers
+ || !self->enemies || !self->alive
+ ) {
+ uninit_map(self);
+ return 0;
+ }
+
+ return 1;
+}
+
+void free_map(map_t *self) {
+ if (self)
+ uninit_map(self);
+
+ free(self);
+}
+
+void uninit_map(map_t *self) {
+ self->CNAME[0] = '!';
+
+ if (self->towers) {
+ array_loop(self->towers, tower, tower_t*) {
+ free_tower(*tower);
+ }
+ }
+
+ if (self->enemies) {
+ array_loop(self->enemies, enemy, enemy_t) {
+ uninit_enemy(enemy);
+ }
+ }
+
+ free (self->data ); self->data = NULL;
+ free_array(self->paths ); self->paths = NULL;
+ free_array(self->towers ); self->towers = NULL;
+ free_array(self->enemies); self->enemies = NULL;
+ free_array(self->alive) ; self->alive = NULL;
+}
+
+int map_path(map_t *self, int x, int y) {
+ if (x < 0 || y < 0)
+ return 0;
+ if (x >= self->width || y >= self->height)
+ return 0;
+ if (self->data[y * self->width + x])
+ return 0;
+
+ path_t *loc = array_new(self->paths);
+ init_path(loc, x, y);
+ loc->index = self->paths->count - 1;
+
+ self->data[y * self->width + x] = loc2any(loc);
+ return 1;
+}
+
+int map_add_tower(map_t *self, tower_t *tower) {
+ int x = tower->x;
+ int y = tower->y;
+ if (x < 0 || y < 0)
+ return 0;
+ if (x >= self->width || y >= self->height)
+ return 0;
+ if (self->data[y * self->width + x])
+ return 0;
+
+ tower_t **ttt = array_new(self->towers);
+ *ttt = tower;
+
+ self->data[y * self->width + x] = tower2any(tower);
+ return 1;
+}
+
+int map_enemy(map_t *self, enemy_t *enemy) {
+ if (!array_push(self->enemies, enemy))
+ return 0;
+
+ return 1;
+}
+
--- /dev/null
+/**
+ * @file map.h
+ * @author Niki
+ * @date 2025
+ *
+ * @brief bla
+ *
+ * blablabla
+ *
+ */
+
+#ifndef MAP_H
+#define MAP_H
+
+#include "cutils/array.h"
+
+#include "any.h"
+
+/**
+ * @brief bla
+ *
+ * blablabla
+ */
+typedef struct {
+ char CNAME[10];
+ int width;
+ int height;
+ any_t **data;
+ array_t *paths;
+ array_t *towers;
+ array_t *enemies;
+ array_t *alive;
+} map_t;
+
+/**
+ * Create a new map.
+ *
+ * @param width the width of the map
+ * @param height the height of the map
+ *
+ * @note always identical to <tt>malloc</tt> + <tt>init_map</tt>
+ *
+ * @see malloc()
+ * @see init_map(map_t *self)
+ *
+ * @return a new map (you must later call `free_map()`)
+ */
+map_t *new_map(int width, int height);
+
+/**
+ * Initialise a new map.
+ *
+ * @param width the width of the map
+ * @param height the height of the map
+ */
+int init_map(map_t *self, int width, int height);
+
+/**
+ * Free the resources held for the given map: you must not use it any more.
+ *
+ * @note always equivalent to <tt>uninit_map</tt> + <tt>free</tt>
+ *
+ * @see uninit_map(map_t *self)
+ * @see free(void *data)
+ */
+void free_map(map_t *self);
+
+/**
+ * Free the resources held for the given map: you must not use it any more
+ * unless you call <tt>init_map</tt> on it again.
+ *
+ * The memory pointed to by <tt>self</tt> is <i>not</i> free'd.
+ *
+ *
+ * @see init_map(map_t *self)
+ */
+void uninit_map(map_t *self);
+
+int map_path(map_t *self, int x, int y);
+
+int map_add_tower(map_t *self, tower_t *tower);
+
+int map_enemy(map_t *self, enemy_t *enemy);
+
+#endif /* MAP_H */
+
--- /dev/null
+/*
+ * TDef: small tower defense game
+ *
+ * Copyright (C) 2025 Niki Roo
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "path.h"
+
+path_t *new_path(int x, int y) {
+ path_t *self = malloc(sizeof(path_t));
+ if (!init_path(self, x, y)) {
+ free(self);
+ self = NULL;
+ }
+
+ return self;
+}
+
+int init_path(path_t *self, int x, int y) {
+ size_t sz = sizeof(self->CNAME);
+ strncpy(self->CNAME, "[loc ", sz);
+ self->CNAME[sz - 2] = ']';
+ self->CNAME[sz - 1] = '\0';
+
+ self->x = x;
+ self->y = y;
+ self->index = -1;
+ self->enemy = NULL;
+
+ return 1;
+}
+
+void free_path(path_t *self) {
+ if (self)
+ uninit_path(self);
+
+ free(self);
+}
+
+void uninit_path(path_t *self) {
+ self->CNAME[0] = '!';
+}
+
--- /dev/null
+/**
+ * @file path.h
+ * @author Niki
+ * @date 2025
+ *
+ * @brief bla
+ *
+ * blablabla
+ *
+ */
+
+#ifndef PATH_H
+#define PATH_H
+
+#include "enemy.h"
+
+/**
+ * @brief bla
+ *
+ * blablabla
+ */
+typedef struct {
+ char CNAME[10];
+ int x;
+ int y;
+ int index;
+ enemy_t *enemy;
+} path_t;
+
+/**
+ * Create a new loc.
+ *
+ * @param x the X coordinate
+ * @param y the Y coordinate
+ *
+ * @note always identical to <tt>malloc</tt> + <tt>init_path</tt>
+ *
+ * @see malloc()
+ * @see init_path(path_t *self)
+ *
+ * @return a new loc (you must later call `free_path()`)
+ */
+path_t *new_path(int x, int y);
+
+/**
+ * Initialise a new loc.
+ *
+ * @param x the X coordinate
+ * @param y the Y coordinate
+ */
+int init_path(path_t *self, int x, int y);
+
+/**
+ * Free the resources held for the given loc: you must not use it any more.
+ *
+ * @note always equivalent to <tt>uninit_path</tt> + <tt>free</tt>
+ *
+ * @see uninit_path(path_t *self)
+ * @see free(void *data)
+ */
+void free_path(path_t *self);
+
+/**
+ * Free the resources held for the given loc: you must not use it any more
+ * unless you call <tt>init_path</tt> on it again.
+ *
+ * The memory pointed to by <tt>self</tt> is <i>not</i> free'd.
+ *
+ *
+ * @see init_path(path_t *self)
+ */
+void uninit_path(path_t *self);
+
+#endif /* PATH_H */
--- /dev/null
+/*
+ * TDef: small tower defense game
+ *
+ * Copyright (C) 2025 Niki Roo
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "any.h"
+#include "map.h"
+#include "engine.h"
+
+void display(map_t *self) {
+ printf("==========\n\n");
+ for (int y = 0 ; y < self->height; y++) {
+ for (int x = 0 ; x < self->width ; x++) {
+ any_t *any = self->data[y * self->width + x];
+ path_t *path = anyloc(any);
+ tower_t *tower = anytower(any);
+ if (tower) {
+ printf("T");
+ } else if (path) {
+ if (path->enemy) {
+ printf("e");
+ }
+ else if (path->index == 0) {
+ printf(">");
+ } else if (path->index == self->paths->count - 1) {
+ printf(">");
+ } else {
+ printf("#");
+ }
+ } else if (any) {
+ printf("?");
+ //printf("\n<%s>\n", any->CNAME);
+ } else {
+ printf(".");
+ }
+ }
+ printf("\n");
+ }
+ printf("\n");
+}
+
+int main(int argc, char **argv) {
+ map_t *map = new_map(6, 4);
+ if (!map) {
+ fprintf(stderr, "Cannot create the map");
+ return 1;
+ }
+
+ map_path(map, 0, 0);
+ map_path(map, 1, 0);
+ map_path(map, 2, 0);
+ map_path(map, 3, 0);
+ map_path(map, 3, 1);
+ map_path(map, 3, 2);
+ map_path(map, 4, 2);
+ map_path(map, 5, 2);
+
+ tower_t *tower = new_tower(2, 1);
+ map_add_tower(map, tower);
+
+ enemy_t *enemy = new_enemy(1);
+ map_enemy(map, enemy);
+
+ engine_t *engine = new_engine(map);
+ engine_tick(engine);
+
+ display(map);
+ engine_tick(engine);
+ display(map);
+
+ free_engine(engine);
+ return 0;
+}
+
--- /dev/null
+/*
+ * TDef: small tower defense game
+ *
+ * Copyright (C) 2025 Niki Roo
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "tower.h"
+
+tower_t *new_tower(int x, int y) {
+ tower_t *self = malloc(sizeof(tower_t));
+ if (!init_tower(self, x, y)) {
+ free(self);
+ self = NULL;
+ }
+
+ return self;
+}
+
+int init_tower(tower_t *self, int x, int y) {
+ size_t sz = sizeof(self->CNAME);
+ strncpy(self->CNAME, "[tower ", sz);
+ self->CNAME[sz - 2] = ']';
+ self->CNAME[sz - 1] = '\0';
+
+ self->x = x;
+ self->y = y;
+
+ return 1;
+}
+
+void free_tower(tower_t *self) {
+ if (self)
+ uninit_tower(self);
+
+ free(self);
+}
+
+void uninit_tower(tower_t *self) {
+ self->CNAME[0] = '!';
+}
+
--- /dev/null
+/**
+ * @file tower.h
+ * @author Niki
+ * @date 2025
+ *
+ * @brief bla
+ *
+ * blablabla
+ *
+ */
+
+#ifndef TOWER_H
+#define TOWER_H
+
+/**
+ * @brief bla
+ *
+ * blablabla
+ */
+typedef struct {
+ char CNAME[10];
+ int x;
+ int y;
+} tower_t;
+
+/**
+ * Create a new tower.
+ *
+ * @param x the X coordinate
+ * @param y the Y coordinate
+ *
+ * @note always identical to <tt>malloc</tt> + <tt>init_tower</tt>
+ *
+ * @see malloc()
+ * @see init_tower(tower_t *self)
+ *
+ * @return a new tower (you must later call `free_tower()`)
+ */
+tower_t *new_tower(int x, int y);
+
+/**
+ * Initialise a new tower.
+ *
+ * @param x the X coordinate
+ * @param y the Y coordinate
+ */
+int init_tower(tower_t *self, int x, int y);
+
+/**
+ * Free the resources held for the given tower: you must not use it any more.
+ *
+ * @note always equivalent to <tt>uninit_tower</tt> + <tt>free</tt>
+ *
+ * @see uninit_tower(tower_t *self)
+ * @see free(void *data)
+ */
+void free_tower(tower_t *self);
+
+/**
+ * Free the resources held for the given tower: you must not use it any more
+ * unless you call <tt>init_tower</tt> on it again.
+ *
+ * The memory pointed to by <tt>self</tt> is <i>not</i> free'd.
+ *
+ *
+ * @see init_tower(tower_t *self)
+ */
+void uninit_tower(tower_t *self);
+
+#endif /* TOWER_H */